Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Programatically testing for openmp support from a python setup script

I'm working on a python project that uses cython and c to speed up time sensitive operations. In a few of our cython routines, we use openmp to further speed up an operation if idle cores are available.

This leads to a bit of an annoying situation on OS X since the default compiler for recent OS versions (llvm/clang on 10.7 and 10.8) doesn't support openmp. Our stopgap solution is to tell people to set gcc as their compiler when they build. We'd really like to do this programmatically since clang can build everything else with no issues.

Right now, compilation will fail with the following error:

clang: error: linker command failed with exit code 1 (use -v to see invocation)
error: Command "cc -bundle -undefined dynamic_lookup -L/usr/local/lib -L/usr/local/opt/sqlite/lib build/temp.macosx-10.8-x86_64-2.7/yt/utilities/lib/geometry_utils.o -lm -o yt/utilities/lib/geometry_utils.so -fopenmp" failed with exit status 1

The relevant portion of our setup script looks like this:

config.add_extension("geometry_utils", 
        ["yt/utilities/lib/geometry_utils.pyx"],
         extra_compile_args=['-fopenmp'],
         extra_link_args=['-fopenmp'],
         libraries=["m"], depends=["yt/utilities/lib/fp_utils.pxd"])

The full setup.py file is here.

Is there a way to programmatically test for openmp support from inside the setup script?

like image 972
ngoldbaum Avatar asked May 14 '13 18:05

ngoldbaum


1 Answers

I was able to get this working by checking to see if a test program compiles:

import os, tempfile, subprocess, shutil    

# see http://openmp.org/wp/openmp-compilers/
omp_test = \
r"""
#include <omp.h>
#include <stdio.h>
int main() {
#pragma omp parallel
printf("Hello from thread %d, nthreads %d\n", omp_get_thread_num(), omp_get_num_threads());
}
"""

def check_for_openmp():
    tmpdir = tempfile.mkdtemp()
    curdir = os.getcwd()
    os.chdir(tmpdir)

    filename = r'test.c'
    with open(filename, 'w', 0) as file:
        file.write(omp_test)
    with open(os.devnull, 'w') as fnull:
        result = subprocess.call(['cc', '-fopenmp', filename],
                                 stdout=fnull, stderr=fnull)

    os.chdir(curdir)
    #clean up
    shutil.rmtree(tmpdir)

    return result
like image 71
ngoldbaum Avatar answered Oct 12 '22 14:10

ngoldbaum