blob: fef060ca0a5152e021ab53d8dc3699fe1441b2f0 [file] [log] [blame]
<!DOCTYPE html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
<head>
<title>Using SystemML with Native BLAS support - SystemML 1.1.0</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="description" content="Using SystemML with Native BLAS support">
<meta name="viewport" content="width=device-width">
<link rel="stylesheet" href="css/bootstrap.min.css">
<link rel="stylesheet" href="css/main.css">
<link rel="stylesheet" href="css/pygments-default.css">
<link rel="shortcut icon" href="img/favicon.png">
</head>
<body>
<!--[if lt IE 7]>
<p class="chromeframe">You are using an outdated browser. <a href="http://browsehappy.com/">Upgrade your browser today</a> or <a href="http://www.google.com/chromeframe/?redirect=true">install Google Chrome Frame</a> to better experience this site.</p>
<![endif]-->
<header class="navbar navbar-default navbar-fixed-top" id="topbar">
<div class="container">
<div class="navbar-header">
<div class="navbar-brand brand projectlogo">
<a href="http://systemml.apache.org/"><img class="logo" src="img/systemml-logo.png" alt="Apache SystemML" title="Apache SystemML"/></a>
</div>
<div class="navbar-brand brand projecttitle">
<a href="http://systemml.apache.org/">Apache SystemML<sup id="trademark"></sup></a><br/>
<span class="version">1.1.0</span>
</div>
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<nav class="navbar-collapse collapse">
<ul class="nav navbar-nav navbar-right">
<li><a href="index.html">Overview</a></li>
<li><a href="https://github.com/apache/systemml">GitHub</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Documentation<b class="caret"></b></a>
<ul class="dropdown-menu" role="menu">
<li><b>Running SystemML:</b></li>
<li><a href="https://github.com/apache/systemml">SystemML GitHub README</a></li>
<li><a href="spark-mlcontext-programming-guide.html">Spark MLContext</a></li>
<li><a href="spark-batch-mode.html">Spark Batch Mode</a>
<li><a href="hadoop-batch-mode.html">Hadoop Batch Mode</a>
<li><a href="standalone-guide.html">Standalone Guide</a></li>
<li><a href="jmlc.html">Java Machine Learning Connector (JMLC)</a>
<li class="divider"></li>
<li><b>Language Guides:</b></li>
<li><a href="dml-language-reference.html">DML Language Reference</a></li>
<li><a href="beginners-guide-to-dml-and-pydml.html">Beginner's Guide to DML and PyDML</a></li>
<li><a href="beginners-guide-python.html">Beginner's Guide for Python Users</a></li>
<li><a href="python-reference.html">Reference Guide for Python Users</a></li>
<li class="divider"></li>
<li><b>ML Algorithms:</b></li>
<li><a href="algorithms-reference.html">Algorithms Reference</a></li>
<li class="divider"></li>
<li><b>Tools:</b></li>
<li><a href="debugger-guide.html">Debugger Guide</a></li>
<li><a href="developer-tools-systemml.html">IDE Guide</a></li>
<li class="divider"></li>
<li><b>Other:</b></li>
<li><a href="contributing-to-systemml.html">Contributing to SystemML</a></li>
<li><a href="engine-dev-guide.html">Engine Developer Guide</a></li>
<li><a href="troubleshooting-guide.html">Troubleshooting Guide</a></li>
<li><a href="release-process.html">Release Process</a></li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">API Docs<b class="caret"></b></a>
<ul class="dropdown-menu" role="menu">
<li><a href="./api/java/index.html">Java</a></li>
<li><a href="./api/python/index.html">Python</a></li>
</ul>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Issues<b class="caret"></b></a>
<ul class="dropdown-menu" role="menu">
<li><b>JIRA:</b></li>
<li><a href="https://issues.apache.org/jira/browse/SYSTEMML">SystemML JIRA</a></li>
</ul>
</li>
</ul>
</nav>
</div>
</header>
<div class="container" id="content">
<h1 class="title">Using SystemML with Native BLAS support</h1>
<!--
-->
<ul id="markdown-toc">
<li><a href="#user-guide" id="markdown-toc-user-guide">User Guide</a> <ul>
<li><a href="#step-1-install-blas" id="markdown-toc-step-1-install-blas">Step 1: Install BLAS</a> <ul>
<li><a href="#option-1-install-intel-mkl" id="markdown-toc-option-1-install-intel-mkl">Option 1: Install Intel MKL</a></li>
<li><a href="#option-2-install-openblas" id="markdown-toc-option-2-install-openblas">Option 2: Install OpenBLAS</a></li>
</ul>
</li>
<li><a href="#step-2-provide-the-location-of-the-native-libraries" id="markdown-toc-step-2-provide-the-location-of-the-native-libraries">Step 2: Provide the location of the native libraries</a></li>
<li><a href="#step-3-set-configuration-property-to-enable-native-blas" id="markdown-toc-step-3-set-configuration-property-to-enable-native-blas">Step 3: Set configuration property to enable native BLAS</a></li>
<li><a href="#common-issues-on-linux" id="markdown-toc-common-issues-on-linux">Common issues on Linux</a></li>
</ul>
</li>
<li><a href="#developer-guide" id="markdown-toc-developer-guide">Developer Guide</a> <ul>
<li><a href="#intro-to-cmake" id="markdown-toc-intro-to-cmake">Intro to CMake</a></li>
</ul>
</li>
</ul>
<p><br /></p>
<h1 id="user-guide">User Guide</h1>
<p>By default, SystemML implements all its matrix operations in Java.
This simplifies deployment especially in a distributed environment.</p>
<p>In some cases (such as deep learning), the user might want to use native BLAS
rather than SystemML&#8217;s internal Java library for performing single-node
operations such matrix multiplication, convolution, etc.</p>
<p>To allow SystemML to use native BLAS rather than internal Java library,
please set the configuration property <code>sysml.native.blas</code> to <code>auto</code>.
Other possible options are: <code>mkl</code>, <code>openblas</code> and <code>none</code>.
The first two options will only attempt to use the respective BLAS libraries.</p>
<p>By default, SystemML will first attempt to use Intel MKL (if installed)
and then OpenBLAS (if installed).
If both Intel MKL and OpenBLAS are not available, SystemML
falls back to its internal Java library.</p>
<p>The current version of SystemML only supports BLAS on <strong>Linux</strong> machines.</p>
<h2 id="step-1-install-blas">Step 1: Install BLAS</h2>
<p>If BLAS is already installed, please skip this step.</p>
<h3 id="option-1-install-intel-mkl">Option 1: Install Intel MKL</h3>
<p>Download and install the <a href="https://software.intel.com/sites/campaigns/nest/">community version of Intel MKL</a>.
Intel requires you to first register your email address and then sends the download link to your email address
with license key. Since we use MKL DNN primitives, we depend on Intel MKL version 2017 or higher.</p>
<ul>
<li>Linux users will have to extract the downloaded <code>.tgz</code> file, execute <code>install.sh</code> and follow the guided setup.</li>
</ul>
<h3 id="option-2-install-openblas">Option 2: Install OpenBLAS</h3>
<p>The default OpenBLAS (via yum/apt-get) uses its internal threading rather than OpenMP,
which can lead to performance degradation when using SystemML. So, instead we recommend that you
compile OpenBLAS from the source instead of installing it with <code>yum</code> or <code>apt-get</code>.</p>
<p>The steps to install OpenBLAS v0.2.20:</p>
<p><code>bash
wget https://github.com/xianyi/OpenBLAS/archive/v0.2.20.tar.gz
tar -xzf v0.2.20.tar.gz
cd OpenBLAS-0.2.20/
make clean
make USE_OPENMP=1
sudo make install
# After installation, you may also want to add `/opt/OpenBLAS/lib` to your LD_LIBRARY_PATH or `java.library.path`.
</code></p>
<p>When using OpenBLAS, we also depend on GNU OpenMP (gomp) which will be installed by GCC.
To find the location of <code>gomp</code> on your system, please use the command <code>ldconfig -p | grep libgomp</code>.
If gomp is available as <code>/lib64/libgomp.so.1</code> instead of <code>/lib64/libgomp.so</code>,
please add a softlink to it:</p>
<p><code>bash
# Centos/RedHat
sudo yum install gcc-c++
# Ubuntu
sudo apt-get install g++
sudo ln -s /lib64/libgomp.so.1 /lib64/libgomp.so
</code></p>
<h2 id="step-2-provide-the-location-of-the-native-libraries">Step 2: Provide the location of the native libraries</h2>
<ol>
<li>
<p>Pass the location of the native libraries using command-line options:</p>
<ul>
<li><a href="http://spark.apache.org/docs/latest/configuration.html">Spark</a>: <code>--conf spark.executorEnv.LD_LIBRARY_PATH=/path/to/blas-n-other-dependencies</code></li>
<li>Java: <code>-Djava.library.path=/path/to/blas-n-other-dependencies</code></li>
</ul>
</li>
<li>
<p>Alternatively, you can add the location of the native libraries (i.e. BLAS and other dependencies)
to the environment variable <code>LD_LIBRARY_PATH</code> (on Linux).
If you want to use SystemML with Spark, please add the following line to <code>spark-env.sh</code>
(or to the bash profile).</p>
<p>export LD_LIBRARY_PATH=/path/to/blas-n-other-dependencies</p>
</li>
</ol>
<p>In cloud environment where you may not be able to set <code>LD_LIBRARY_PATH</code> or <code>spark.executorEnv.LD_LIBRARY_PATH</code>
before starting spark, you can use set the configuration property <code>sysml.native.blas.directory</code>. For example:</p>
<p><code>python
mlCtx.setConfigProperty("sysml.native.blas.directory", "/path/to/blas-n-other-dependencies")
</code></p>
<h2 id="step-3-set-configuration-property-to-enable-native-blas">Step 3: Set configuration property to enable native BLAS</h2>
<p>The configuration property <code>sysml.native.blas</code> can be either set in the file <code>SystemML-config.xml</code>
or using <code>setConfigProperty</code> method of <code>MLContext</code> or <code>mllearn</code> classes. For example:</p>
<p><code>python
mlCtx.setConfigProperty("sysml.native.blas", "openblas")
</code></p>
<h2 id="common-issues-on-linux">Common issues on Linux</h2>
<ul>
<li>Unable to load <code>gomp</code>.</li>
</ul>
<p>First make sure if gomp is available on your system.</p>
<pre><code>ldconfig -p | grep libgomp
</code></pre>
<p>If the above command returns no results, then you may have to install <code>gcc</code>.
On the other hand, if the above command only returns libgomp with major suffix (such as <code>so.1</code>),
then please execute the below command:</p>
<pre><code>sudo ln -s /lib64/libgomp.so.1 /usr/lib64/libgomp.so
</code></pre>
<ul>
<li>Unable to load <code>mkl_rt</code>.</li>
</ul>
<p>By default, Intel MKL libraries will be installed in the location <code>/opt/intel/mkl/lib/intel64/</code>.
Make sure that this path is accessible to Java as per instructions provided in the above section.</p>
<ul>
<li>Unable to load <code>openblas</code>.</li>
</ul>
<p>By default, OpenBLAS libraries will be installed in the location <code>/opt/OpenBLAS/lib/</code>.
Make sure that this path is accessible to Java as per instructions provided in the above section.</p>
<ul>
<li>Using OpenBLAS without OpenMP can lead to performance degradation when using SystemML.</li>
</ul>
<p>You can check if the OpenBLAS on you system is compiled with OpenMP or not using following commands:
If you don&#8217;t see any output after the second command, then OpenBLAS installed on your system is using its internal threading.
In this case, we highly recommend that you reinstall OpenBLAS using the above commands.</p>
<pre><code>$ ldconfig -p | grep libopenblas.so
libopenblas.so (libc6,x86-64) =&gt; /opt/OpenBLAS/lib/libopenblas.so
$ ldd /opt/OpenBLAS/lib/libopenblas.so | grep libgomp
libgomp.so.1 =&gt; /lib64/libgomp.so.1
</code></pre>
<ul>
<li>Using MKL can lead to slow performance for convolution instruction.</li>
</ul>
<p>We noticed that double-precision MKL DNN primitives for convolution instruction
is considerably slower than than the corresponding single-precision MKL DNN primitives
as of MKL 2017 Update 1. We anticipate that this performance bug will be fixed in the future MKL versions.
Until then or until SystemML supports single-precision matrices, we recommend that you use OpenBLAS when using script with <code>conv2d</code>.</p>
<p>Here are the end-to-end runtime performance in seconds of 10 <code>conv2d</code> operations
on randomly generated 64 images of size 256 X 256 with sparsity 0.9
and 32 filter of size 5x5 with stride = [1,1] and pad=[1,1].</p>
<table>
<thead>
<tr>
<th>&#160;</th>
<th>MKL</th>
<th>OpenBLAS</th>
</tr>
</thead>
<tbody>
<tr>
<td>Single-precision, channels=3</td>
<td>5.144</td>
<td>7.918</td>
</tr>
<tr>
<td>Double-precision, channels=3</td>
<td>12.599</td>
<td>8.688</td>
</tr>
<tr>
<td>Single-precision, channels=32</td>
<td>10.765</td>
<td>21.963</td>
</tr>
<tr>
<td>Double-precision, channels=32</td>
<td>71.118</td>
<td>34.881</td>
</tr>
</tbody>
</table>
<p>Setup used in the above experiment:
1. Intel MKL 2017 Update 1, OpenBLAS compiled with GNU OpenMP from source using <code>g++</code>.
2. CPU: <code>Intel(R) Xeon(R) CPU E5-2620 v3 @ 2.40GHz</code></p>
<h1 id="developer-guide">Developer Guide</h1>
<p>This section describes how to compile shared libraries in the folder <code>src/main/cpp/lib</code>.
This is required when the developer makes changes to cpp directory or while validating the source package during the release process.</p>
<h2 id="intro-to-cmake">Intro to CMake</h2>
<p>If you are familiar with cmake, skip this section.</p>
<p>In a regular project with a Makefile, the compiled object files are placed in the same directory as the source.
Sometimes we don&#8217;t want to pollute the source tree. We might also want to have different binaries for different configurations. For instance, if we want to link a binary with separate libraries.
CMake supports out of source tree builds. As an illustration, you can create a directory called &#8220;BUILD&#8221; and invoke cmake like so : <code>cmake &lt;path/to/source&gt;</code>. The makefile and other config files are placed in this &#8220;BUILD&#8221; directory. You can now say <code>make</code> and the compiled objects and binary files are created in this directory. You can then create another &#8220;BUILD2&#8221; directory and repeat the process.
You can pass options to cmake as well. In this instance, it might be to specify whether to build with Intel MKL or OpenBLAS. This can be done from the command line with a &#8220;-D&#8221; appended to it, but more interestingly, it can also be done form a n-curses GUI which is invoked as <code>ccmake &lt;path/to/source&gt;</code>. (You may need to install this separately).
Also, the C, C++ compilers and their flags are picked up by cmake when set in standard environment variables. These are respectively <code>CC</code>, <code>CXX</code>, <code>CFLAGS</code> &amp; <code>CXFLAGS</code>. As an example, they may be specified as:</p>
<pre><code>CXX=gcc-6 cmake ..
</code></pre>
<p>For this project, I typically make a directory in the <code>cpp</code> folder (this folder) and name it the config I use. For instance, <code>INTEL</code> for Intel MKL and <code>OPENBLAS</code> for OpenBLAS.</p>
<ul>
<li>
<p>Install <code>g++</code>, OpenBLAS and MKL using the above instructions</p>
</li>
<li>
<p>Set <code>JAVA_HOME</code> to JDK.</p>
</li>
</ul>
<p><code>bash
export JAVA_HOME=&lt;path to JDK 1.8&gt;
</code></p>
<ul>
<li>Install cmake</li>
</ul>
<p><code>bash
# Centos/RedHat
sudo yum install cmake3
# Ubuntu
sudo apt-get install cmake
</code></p>
<ul>
<li>Compile the libs using the below script.</li>
</ul>
<p><code>bash
mkdir INTEL &amp;&amp; cd INTEL
cmake -DUSE_INTEL_MKL=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_CXX_FLAGS="-DUSE_GNU_THREADING -m64" ..
make install
cd ..
mkdir OPENBLAS &amp;&amp; cd OPENBLAS
cmake -DUSE_OPEN_BLAS=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_CXX_FLAGS="-m64" ..
make install
cd ..
# The below script helps maintain this document as well as avoid accidental inclusion of non-standard dependencies.
./check-dependency-linux-x86_64.sh
</code></p>
<p>The generated library files are placed in src/main/cpp/lib. This location can be changed from the CMakeLists.txt file.</p>
<p>The above script also validates whether additional dependencies have been added while compiling and warns the developer.<br />
The current set of dependencies other than MKL and OpenBLAS, are as follows:</p>
<ul>
<li>GNU Standard C++ Library: <code>libstdc++.so.6</code></li>
<li>GCC version 4.8 shared support library: <code>libgcc_s.so.1</code></li>
<li>The GNU libc libraries: <code>libm.so.6, libdl.so.2, libc.so.6, libpthread.so.0</code></li>
<li>GCC OpenMP v3.0 shared support library: <code>libgomp.so.1</code></li>
<li>Additional OpenBLAS dependencies: Fortran runtime (<code>libgfortran.so.3</code>) and GCC <code>__float128</code> shared support library (<code>libquadmath.so.0</code>)</li>
</ul>
<p>If CMake cannot detect your OpenBLAS installation, set the <code>OpenBLAS_HOME</code> environment variable to the OpenBLAS Home.</p>
</div> <!-- /container -->
<script src="js/vendor/jquery-1.12.0.min.js"></script>
<script src="js/vendor/bootstrap.min.js"></script>
<script src="js/vendor/anchor.min.js"></script>
<script src="js/main.js"></script>
<!-- Analytics -->
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-71553733-1', 'auto');
ga('send', 'pageview');
</script>
<!-- MathJax Section -->
<script type="text/x-mathjax-config">
MathJax.Hub.Config({
TeX: { equationNumbers: { autoNumber: "AMS" } }
});
</script>
<script>
// Note that we load MathJax this way to work with local file (file://), HTTP and HTTPS.
// We could use "//cdn.mathjax...", but that won't support "file://".
(function(d, script) {
script = d.createElement('script');
script.type = 'text/javascript';
script.async = true;
script.onload = function(){
MathJax.Hub.Config({
tex2jax: {
inlineMath: [ ["$", "$"], ["\\\\(","\\\\)"] ],
displayMath: [ ["$$","$$"], ["\\[", "\\]"] ],
processEscapes: true,
skipTags: ['script', 'noscript', 'style', 'textarea', 'pre']
}
});
};
script.src = ('https:' == document.location.protocol ? 'https://' : 'http://') +
'cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML';
d.getElementsByTagName('head')[0].appendChild(script);
}(document));
</script>
</body>
</html>