Skip to content

Build py-numpy with MKL#2361

Closed
glennpj wants to merge 1 commit intospack:developfrom
glennpj:numpy_blas
Closed

Build py-numpy with MKL#2361
glennpj wants to merge 1 commit intospack:developfrom
glennpj:numpy_blas

Conversation

@glennpj
Copy link
Copy Markdown
Contributor

@glennpj glennpj commented Nov 18, 2016

This PR gets a GCC built python to use MKL for blas/lapack. This is not perfect and I
have put comments for TODO items.

The changes to intel-parallel-studio are to get the correct library path for blas. I was
using that to attempt to use it but there were a couple of other issues. The changes to
the mkl package are to get the proper paths in the environment module, similar to what
was done previously for the intel-parallel-studio package.

For py-numpy itself, the section title for the defaults changed from DEFAULTS to ALL with
numpy-1.10 so that is configured accordingly. Also, for MKL to be used there must be a
section called, '[mkl]'. Finally, the mkl_rt library is needed, especially when built
with GCC. As such, that library is made explicit in the [mkl] section of the config file.

This PR gets a GCC built python to use MKL for blas/lapack. This is not perfect and I
have put comments for TODO items.

The changes to intel-parallel-studio are to get the correct library path for blas. I was
using that to attempt to use it but there were a couple of other issues. The changes to
the mkl package are to get the proper paths in the environment module, similar to what
was done previously for the intel-parallel-studio package.

For py-numpy itself, the section title for the defaults changed from DEFAULTS to ALL with
numpy-1.10 so that is configured accordingly. Also, for MKL to be used there must be a
section called, '[mkl]'. Finally, the mkl_rt library is needed, especially when built
with GCC. As such, that library is made explicit in the [mkl] section of the config file.
env.prepend_path('LD_LIBRARY_PATH',
join_path(self.prefix, 'lib', 'intel64'))
env.prepend_path('LIBRARY_PATH',
join_path(self.prefix, 'lib', 'intel64'))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So you remove, and then prepend, and then prepend a second time?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, looks like duplicates sneaked in there. I will remove those.

Copy link
Copy Markdown
Member

@davydden davydden left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, for MKL to be used there must be a section called, '[mkl]'.

i think it can, but it does NOT have to.

Finally, the mkl_rt library is needed, especially when built with GCC.

from my experience on Ubuntu16 with GCC@5.4 i never had any needs to use mkl_rt anywhere when building trilinos, petsc, mumps, superlu_dist, hypre and a number of other linear algebra packages.

I must admit i never tried building py-numpy with MKL, but I would be surprised if it does not work.


def setup_environment(self, spack_env, env):
# Remove paths that were guessed but are incorrect for this package.
env.remove_path('LIBRARY_PATH',
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK Spack does not use LD_LIBRARY_PATH or alike anywhere, everything is RPATH'ed, why do you need all those changes?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in other words, if for any packages in Spack you need to set LD_LIBRARY_PATH to have something working, then something is wrong.

mkl_libs = find_libraries(
mkl_integer + ['libmkl_core'] + mkl_threading,
root=join_path(self.prefix.lib, 'intel64'),
root=join_path(self.prefix, 'mkl', 'lib', 'intel64'),
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that looked like a bug, it's probably better have it in a separate commit.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe in a separate PR which can be quickly merged. Then you will rebase this one to get rid of this change.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with this change being in this PR. You can't really test this PR without it I imagine.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you surely can't. I am just saying to make things fast one could submit this change as a stand-alone PR, but still keep it here. Once a stand alone PR is merged, one can re-base this one on develop.

But i don't really insist on this, just explain my rationale.

# mkl that package will not work here with a non-Intel
# compiler due to header collision.
f.write('[mkl]\n')
f.write('libraries=mkl_rt\n')
Copy link
Copy Markdown
Member

@davydden davydden Nov 18, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i am not in favour of this change. join(lapackblas.names) depends on whole lot of variants (32/64 bits, threaded/serial, and alike). Once you use mkl_rt here it is now up to environment variable. In other words you introduce a way to use different BLAS/LAPACK in DAG.

What was wrong exactly with 'join(lapackblas.names)? At the end of the day we give the complete library lists there and it is bound to work. At least it does in a number of other packages without a need to use mkl_rt anywhere.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you please try keeping f.write('libraries=%s\n' % ','.join(lapackblas.names)) unconditionally while using f.write('[mkl]\n') for MKL if py-numpy really want it this way?

@davydden
Copy link
Copy Markdown
Member

p.s. if py-numpy config system is crazy, so be it, but please try avoid using mkl_rt for consistency with other libraries and stick with lapackblas.names.

@glennpj
Copy link
Copy Markdown
Contributor Author

glennpj commented Nov 18, 2016

Okay; I guess I should have split this in multiple PRs. Regarding LD_LIBRARY_PATH, that is needed for the environment module not for the build.

Regarding the other comments, yes, the [mkl] section is needed in the numpy site.cfg, unless the config is removed it would fall back to MKLROOT. It seemed better to have the section in the config rather than rely on the environment variable.

Using mkl_rt is needed for numpy as far as I can tell. Intel states this as well here: https://software.intel.com/en-us/articles/numpyscipy-with-intel-mkl

Building with GNU Compiler chain:

Make modifications to MKL section in the site.cfg as mentioned above. To build numpy and scipy with Gnu compilers, in the site.cfg file, you must link with mkl_rt only and any other linking method will not work.

Using mkl_rt can be directed by environment variables at run time but it does not depend on them.

I think that addresses the bulk of the comments. I am not really sure how to proceed here given the comments.

@davydden
Copy link
Copy Markdown
Member

davydden commented Nov 18, 2016

Regarding LD_LIBRARY_PATH, that is needed for the environment module not for the build.

still don't understand why. Everything is built with RPATH's in Spack, so LD_LIBRARY_PATH shall not be used at all.

Using mkl_rt is needed for numpy as far as I can tell.

I am not saying it does not build with mkl_rt, I am saying it is NOT the only way, actually it is even mentioned in SciPy's website:
https://www.scipy.org/scipylib/building/linux.html#intel-mkl-11-0-updated-dec-2012

So please try using lapackblas.names.

Using mkl_rt can be directed by environment variables at run time but it does not depend on them.

it's not about that. The whole point of NOT using it is to provide consistent BLAS/LAPACK everwhere in the DAG. That is done through the extra class which holds libraries and have methods like names() and alike.

I am not really sure how to proceed here given the comments.

Please try (i) not to set LD_LIBRARY_PATH, it shall not be needed; (ii) use lapackblas.names, the link above suggests that it shall work.

p.s. edited based on @adamjstewart answer below.

@davydden
Copy link
Copy Markdown
Member

davydden commented Nov 18, 2016

FYI, from SciPy org (emphasize is mine):

Instead of the layered linking approach for the Intel® MKL as shown above, you MAY also use the dynamic interface lib mkl_rt.lib.

"shown above" is

[mkl]
library_dirs = /opt/intel/composer_xe_2013/mkl/lib/intel64
include_dirs = /opt/intel/composer_xe_2013/mkl/include
mkl_libs = mkl_intel_lp64,mkl_intel_thread,mkl_core

@adamjstewart
Copy link
Copy Markdown
Member

Regarding LD_LIBRARY_PATH, that is needed for the environment module not for the build.

still don't understand why. Everything is built with RPATH's in Spack, so LD_LIBRARY_PATH shall not be used at all.

Python packages (like py-scipy) don't currently use RPATH. Also, anyone loading the MKL module outside of Spack for building their own code would surely want to set LD_LIBRARY_PATH. We do for all packages, it just so happens that the directory is wrong for MKL.

@davydden
Copy link
Copy Markdown
Member

@adamjstewart :

Python packages (like py-scipy) don't currently use RPATH.

that explains a lot, thanks

@glennpj
Copy link
Copy Markdown
Contributor Author

glennpj commented Nov 18, 2016

@davydden Note the caveat that GCC requires mkl_rt, not the intel compiler, which is what your link refers to. Also, I did try to make it work with the standard blas_libs before agreeing with Intel that GCC requires mkl_rt.

Anyway, I will close this PR as clearly I have missed the mark.

@glennpj glennpj closed this Nov 18, 2016
@davydden
Copy link
Copy Markdown
Member

davydden commented Nov 18, 2016

Note the caveat that GCC requires mkl_rt

but why? As I said above i had no problems building with MKL (without mkl_rt) and GCC. Can you elaborate?

Also, I did try to make it work with the standard blas_libs

what was the problem?

@davydden
Copy link
Copy Markdown
Member

davydden commented Nov 18, 2016

for the record, Intel's link advisor with Select compiler: Gnu C/C++ says

-L${MKLROOT}/lib -Wl,-rpath,${MKLROOT}/lib -lmkl_intel_lp64 -lmkl_sequential -lmkl_core -lpthread -lm -ldl

so i see no reason why GCC would need mkl_rt for py-numpy.

@glennpj glennpj deleted the numpy_blas branch November 19, 2016 01:43
@krafczyk krafczyk requested review from krafczyk and removed request for krafczyk February 3, 2017 21:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants