Skip to content

Fix py-scipy build with intel compilers#8817

Closed
s-sajid-ali wants to merge 34 commits intospack:developfrom
s-sajid-ali:intel_scipy_test
Closed

Fix py-scipy build with intel compilers#8817
s-sajid-ali wants to merge 34 commits intospack:developfrom
s-sajid-ali:intel_scipy_test

Conversation

@s-sajid-ali
Copy link
Copy Markdown
Contributor

@s-sajid-ali s-sajid-ali commented Jul 27, 2018

Closes #8616, closes #3204
(Feel free to reopen the second issue if the goal is to not link to mkl_rt)

Need to resolve the F90 env variable setting first. I was able to install with --dirty and this build recipe.

Refer to 1.
Numpy parallel builds now work. Refer to 2.

Test matrix :

(Note : Known issues with intel-mkl while testing.)

CentOS/Py 2.7.14 Intel-MKL OpenBLAS
Intel18 [ ] [ ]
GCC 7.3.0 Pass Pass
Clang 6.0.1 [ ] [ ]
CentOS/Py 3.6.6 Intel-MKL OpenBLAS
Intel18 Pass [ ]
GCC 7.3.0 Pass Pass
Clang 6.0.1 [ ] [ ]
MacOS/Py 2.7.15 Intel-MKL OpenBLAS
Intel18 [ ] [ ]
GCC 7.3.0 [ ] [ ]
Clang 6.0.1 [ ] [ ]
MacOS/Py 3.6.6 Intel-MKL OpenBLAS
Intel18 [ ] [ ]
GCC 7.3.0 [ ] [ ]
Clang 6.0.1 [ ] [ ]

Bash script to automate building & testing :

Note : There's an issue with intel compilers and py-scipy that requires one to explicitly set F90.
PS : Edit the location where spack is present and git checkout statement appropriately

pyver="3.6.6"

for compiler in gcc@7.3.0 intel@18.0.3
do
        if [ "$compiler" = "intel@18.0.3" ]
        then
                export F90="/home/sajid/packages/spack/lib/spack/env/intel/ifort"
        fi

        for mathlib in openblas@0.3.2
        do
                cd ~/packages/spack
                git checkout intel_scipy_test
                cd ~
                spack install py-scipy@1.1.0 ^py-numpy@1.15.0+blas+lapack ^$mathlib ^python@$pyver %$compiler
                spack activate py-scipy@1.1.0 ^$mathlib ^python@$pyver %$compiler
                if [ "$mathlib" = "intel-mkl" ]
                then
                KMP_INIT_AT_FORK=FALSE python test_numpy_scipy.py &> py$pyver.$mathlib.$compiler.txt
                else
                python test_numpy_scipy.py &> py$pyver.$mathlib.$compiler.txt
                fi
                spack load python@$pyver %$compiler
                spack deactivate py-scipy@1.1.0 ^$mathlib ^python@$pyver %$compiler
                spack deactivate py-numpy@1.15.0 ^$mathlib ^python@$pyver %$compiler

        done
done

Test script :

#Show python version, OS version, test numpy and scipy.                 
import sys,platform                                                     
import numpy                                                            
import scipy                                                            
                                                                        
if sys.version[0]>2:                                                    
    print('\n'+'Python version'+'\n')                                   
    print(sys.version)                                                  
    print('\n'+'OS info'+'\n')                                          
    print(platform.platform())                                          
    print('\n'+'Numpy BLAS/Lapack linkage'+'\n')                        
    numpy.__config__.show()                                             
    print('\n'+'Scipy BLAS/Lapack linkage'+'\n')                        
    scipy.__config__.show()                                             
    print('\n\n')                                                       
    numpy.test('full')                                                  
    scipy.test('full')                                                  
else :                                                                  
    print '\n'+'Python version'+'\n'                                    
    print sys.version                                                   
    print '\n'+'OS info'+'\n'                                           
    print platform.platform()                                           
    print '\n'+'Numpy BLAS/Lapack linkage'+'\n'                         
    numpy.__config__.show()                                             
    print'\n'+'Scipy BLAS/Lapack linkage'+'\n'                          
    scipy.__config__.show()                                             
    print '\n\n'                                                        
    numpy.test('full')                                                  
    scipy.test('full')                                                  

@s-sajid-ali s-sajid-ali changed the title [WIP] Fix py-scipy build [WIP] Fix py-scipy build with intel compilers Jul 27, 2018
@s-sajid-ali s-sajid-ali changed the title [WIP] Fix py-scipy build with intel compilers [help needed] Fix py-scipy build with intel compilers Jul 31, 2018
	modified:   var/spack/repos/builtin/packages/py-scipy/package.py
@s-sajid-ali s-sajid-ali changed the title [help needed] Fix py-scipy build with intel compilers Fix py-scipy build with intel compilers Aug 5, 2018
Copy link
Copy Markdown
Member

@adamjstewart adamjstewart left a comment

Choose a reason for hiding this comment

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

Thanks for trying to fix Numpy/Scipy + Intel! I've been having problems with them for the longest time. I've also tried my own fixes in #3207 and #4545 but failed miserably. For this to get merged, it will require testing by several people on multiple OSes with multiple compilers and BLAS/LAPACK libraries. It would be good to set up a testing table like in #3207 (comment) to see what still needs to be tested.


depends_on('py-nose@1.0.0:', type='test')
depends_on('py-nose@1.0.0:', type='test', when="@:1.14.5")
depends_on('py-pytest', type='test', when="@1.15.0:")
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 would do:

depends_on('py-nose@1.0.0:', type='test', when='@:1.14')
depends_on('py-pytest', type='test', when='@1.15:')

just in case they release a 1.14.6 bugfix someday.

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.

Done.

if spec['python'].version < Version('3.5'):
args = ['-j', str(make_jobs)]

return args
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 your commit message, you mention that numpy fixed its parallel builds. So why remove the parallel flag? Is it done internally now? It looks like the -j flag still exists:

$ python setup.py build --help
...
  --parallel (-j)    number of parallel build jobs
...

run_env.prepend_path('CPATH', include_path)

# Do the usual with gcc
def get_phases(self):
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.

What is get_phases? It seems like you're trying to set the phases to run based on the compiler, but I don't see how this works.

P.S. No other package in Spack changes its phases dynamically, they are all static as far as I know.

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.

I wrote this function because I wanted to build and install in one step only for intel compilers. If using GCC/Clang, do the usual and if using Intel, build and install in one step. Is there a better way to do this ?

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 don't know of any package that does this. If it's possible, it would look something like this:

@property
def phases(self):
    if self.spec.satisfies('%intel'):
        return [...]
    else:
        return [...]

@alalazo might know if this is kosher or not. Do you have to use different phases? Could you use the same phases for both?

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.

I'm just doing what the docs ask me to with no modifications whatsover so yes. If that has to be avoided then someone needs to check it by breaking it into multiple steps and checking the libraries being linked at each stage. That would have the same multimethods issue where the build and install args would be different depending on the compiler used.

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.

Does having dynamic phases break anything ? If it doesn't then this approach is preferable because it's better not to mess with whatever assumptions the people who develop numpy.disutils might have taken rather than force static phases only to discover that some assumption was violated (which might not be the case but I wonder if it's worth the effort).


def install(self, spec, prefix):
install_args = self.install_args(self, prefix)
self.setup_py(*install_args)
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.

This shouldn't be necessary. If it is, it is a regression of an old bug that required both the default and @when functions to be present in a package.

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.

//required both the default and @when functions to be present in a package// I just followed the docs which say The default version of decorated methods must always come first. Should I just remove the default cases completely then ?

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.

Yep, they should already be present in the base class, no need to override them

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.

Done.

install_args = self.install_args(spec, prefix)
self.setup_py('config', '--compiler=intelem', 'build_clib',
'--compiler=intelem', 'build_ext',
'--compiler=intelem', 'install', *install_args)
Copy link
Copy Markdown
Member

@adamjstewart adamjstewart Aug 5, 2018

Choose a reason for hiding this comment

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

Do they have to be run all at the same time? I actually tried something like this back in #4545 but haven't had time to work on that since starting grad school. I vaguely recall having some problems with numpy. I'm wondering if for some reason they have to be run at the same time.

I also tried using intelem back in #3207 but I ran into problems: #3207 (comment). I feel like I may have had a conversation with @wscullin about this...

Copy link
Copy Markdown
Contributor Author

@s-sajid-ali s-sajid-ali Aug 5, 2018

Choose a reason for hiding this comment

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

As I mentioned in #3204 (comment), this might have been happening because loading the intel compiler via module file sets MKL_ROOT. Also, in my case it was only setting the F77 variable and not the F90 variable. This caused all sorts of issues that I resolved by manually editing the module file for intel compiler. Spack needs to eventually be able to work better with the intel compilers but that's something that should succeed #7469.

# https://github.com/spack/spack/issues/7927
# https://github.com/scipy/scipy/issues/7112
if spec['python'].version < Version('3.5'):
args = ['-j', str(make_jobs)]
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 wonder if we should still keep this. What version of Numpy fixed the problem?

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.

It was tagged for the 1.13.0 release as per https://github.com/numpy/numpy/pull/9050#issuecomment-300209782.

So, should I switch the statement to if self.version >= Version('1.13.0'): instead ?

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.

Done.

def build_args(self, spec, prefix):
args = []
# From NumPy 1.10.0 on it's possible to do a parallel build.
if self.version >= Version('1.10.0'):
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.

This isn't needed, as far as I know, Scipy has always supported a parallel build. We might want to keep the stuff below though, at least for older versions of scipy. Depends on when the bug was fixed.

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.

The bug was in numpy.disutils so one can't infer from the scipy version when it was fixed. Is there a way to check what numpy version was used in the concretization ?

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.

if self.spec.satifies('^py-numpy@1.2.3:'):

might work.

@s-sajid-ali
Copy link
Copy Markdown
Contributor Author

s-sajid-ali commented Aug 6, 2018

I'm unable to build openblas@0.3.2%intel@18.0.3 at the moment. Should the test matrix be changed to BLIS or ATLAS instead ?

For Clang, is it recommended that one installs flang and sets cc to the llvm that comes with it ?

@adamjstewart
Copy link
Copy Markdown
Member

OpenBLAS is the default BLAS provider. If that doesn't work, we've got a problem. Does it work for you on develop?

@s-sajid-ali
Copy link
Copy Markdown
Contributor Author

s-sajid-ali commented Aug 6, 2018

It fails on develop. Build fail info.

The issue is that libopenblas.so somehow picked up a gfortran@7.3.0 library despite me setting F90. I should probably open a new issue for this sometime but that's got nothing to do with numpy.

@adamjstewart
Copy link
Copy Markdown
Member

Let's let others test OpenBLAS then. It has to be working for someone 😆

@s-sajid-ali
Copy link
Copy Markdown
Contributor Author

Sure, I've posted a bash script for the same to make it easier.

Also, it would be great to have BLIS in spack.

if '^openblas' in spec:
f.write('[openblas]\n')
f.write('libraries=%s\n' % names)
if '^blis' in spec:
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.

Use elif

@s-sajid-ali
Copy link
Copy Markdown
Contributor Author

s-sajid-ali commented Aug 21, 2018

@adamjstewart : Can this PR be tested/reviewed on macOS ?

PS : all python 2.7 ^intel tests fail due to #9037. I was able to run the tests for ^gcc@7.3.0 by installing py-pytest from pip but that's all I can do at the moment until openblas^intel and py-pytest^python@2.7.14 is fixed.

PPS: Do you have knowledge of flang/clang compilers for python packages ?

@s-sajid-ali s-sajid-ali mentioned this pull request Aug 2, 2019
26 tasks
@adamjstewart
Copy link
Copy Markdown
Member

I think there's a good chance #12170 will fix your problems as numpy's build system has gotten a lot smarter in the latest release. If not, you'll need to rebase this PR once #12170 is merged.

@s-sajid-ali
Copy link
Copy Markdown
Contributor Author

s-sajid-ali commented Aug 6, 2019

Once #12170 is merged, I can check whether py-numpy/py-scipy build with intel and see what to make of this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

scipy build fails for python 3.5 and 3.6 Unable to build Numpy with Intel 17

2 participants