Skip to content
This repository was archived by the owner on Apr 23, 2025. It is now read-only.

Update building and testing with llvm-openmp-dev #34

Merged
merged 1 commit into from
Sep 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 19 additions & 25 deletions .github/workflows/pyomp-ci.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
name: Test Numba PyOMP

on:
push:
pull_request:
workflow_dispatch:

jobs:
build-and-test:
strategy:
matrix:
os: [ubuntu-latest]
#os: [ubuntu-latest, macOS-latest]
name: Build Numba PyOMP for platform ${{ matrix.os }}
os: [ubuntu-latest, macOS-latest]
name: Build and test Numba PyOMP ${{ matrix.os }}
runs-on: ${{ matrix.os }}
defaults:
run:
Expand All @@ -27,18 +25,13 @@ jobs:
- name: Build Numba PyOMP
run: |
conda create -c python-for-hpc -c conda-forge --override-channels -n test-numba-pyomp \
llvmdev llvmlite numpy=1.24 lark-parser cffi python=3.10
compilers llvmdev=14.0.6 numpy=1.24 lark-parser cffi python=3.10 \
llvmlite=pyomp_0.40 \
llvm-openmp-dev=14.0.6
conda init
conda activate test-numba-pyomp
pushd ${GITHUB_WORKSPACE}
MACOSX_DEPLOYMENT_TARGET=10.10 python setup.py build_static build_ext build install --single-version-externally-managed --record=record.txt
mkdir -p ${GITHUB_WORKSPACE}/bin
mkdir -p ${GITHUB_WORKSPACE}/lib
cp ${CONDA_PREFIX}/bin/clang ${GITHUB_WORKSPACE}/bin
cp ${CONDA_PREFIX}/bin/opt ${GITHUB_WORKSPACE}/bin
cp ${CONDA_PREFIX}/bin/llc ${GITHUB_WORKSPACE}/bin
cp ${CONDA_PREFIX}/bin/llvm-link ${GITHUB_WORKSPACE}/bin
cp ${CONDA_PREFIX}/lib/lib*omp* ${GITHUB_WORKSPACE}/lib
popd
- name: Test Numba PyOMP Host
env:
Expand All @@ -53,16 +46,17 @@ jobs:
numba -s
python -m numba.runtests -v -- numba.tests.test_openmp
popd
- name: Test Numba PyOMP Device target host device(1)
env:
TEST_DEVICES: 1
RUN_TARGET: 1
run: |
# Must be in a different directory to run tests.
pushd ${RUNNER_WORKSPACE}
conda init
conda activate test-numba-pyomp
numba -h
numba -s
python -m numba.runtests -v -- numba.tests.test_openmp.TestOpenmpTarget
popd
# TODO: Re-enable when fixed.
#- name: Test Numba PyOMP Device target host device(1)
# env:
# TEST_DEVICES: 1
# RUN_TARGET: 1
# run: |
# # Must be in a different directory to run tests.
# pushd ${RUNNER_WORKSPACE}
# conda init
# conda activate test-numba-pyomp
# numba -h
# numba -s
# python -m numba.runtests -v -- numba.tests.test_openmp.TestOpenmpTarget
# popd
2 changes: 0 additions & 2 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ include README.rst setup.py runtests.py versioneer.py CHANGE_LOG LICENSE
recursive-include numba *.c *.cpp *.h *.hpp *.inc
recursive-include docs *.ipynb *.txt *.py Makefile *.rst
recursive-include examples *.py
recursive-include numba/lib *.bc lib*omp*so
recursive-include numba/bin opt llc llvm-link clang

prune docs/_build
prune docs/gh-pages
Expand Down
23 changes: 9 additions & 14 deletions buildscripts/gitlab/ci-build-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,11 @@ machine=${hostname//[0-9]/}

source /usr/workspace/ggeorgak/${machine}/miniconda3-env.sh
conda create -y -p ${CI_BUILDS_DIR}/test-numba-pyomp -c python-for-hpc -c conda-forge --override-channels \
llvmdev llvmlite numpy=1.24 lark-parser cffi python=3.10
llvmdev=14.0.6 numpy=1.24 lark-parser cffi python=3.10 \
llvm-openmp-dev=14.0.6 \
llvmlite=pyomp_0.40
conda activate ${CI_BUILDS_DIR}/test-numba-pyomp
pushd ${CI_PROJECT_DIR}
mkdir -p ${CI_PROJECT_DIR}/numba/bin
mkdir -p ${CI_PROJECT_DIR}/numba/lib
cp ${CONDA_PREFIX}/bin/clang ${CI_PROJECT_DIR}/numba/bin
cp ${CONDA_PREFIX}/bin/opt ${CI_PROJECT_DIR}/numba/bin
cp ${CONDA_PREFIX}/bin/llc ${CI_PROJECT_DIR}/numba/bin
cp ${CONDA_PREFIX}/bin/llvm-link ${CI_PROJECT_DIR}/numba/bin
cp ${CONDA_PREFIX}/lib/lib*omp* ${CI_PROJECT_DIR}/numba/lib
MACOSX_DEPLOYMENT_TARGET=10.10 python setup.py \
build_static build_ext build install --single-version-externally-managed --record=record.txt || { echo "Build failed"; exit 1; }
popd
Expand All @@ -25,17 +20,17 @@ echo "=> Test Numba PyOMP Host"
TEST_DEVICES=0 RUN_TARGET=0 python -m numba.runtests -- numba.tests.test_openmp \
|| { echo "Test Numba PyOMP Host failed"; exit 1; }


if [[ "${machine}" == "lassen" ]]; then
echo "=> Test Numba PyOMP Target GPU device(0)"
TEST_DEVICES=0 RUN_TARGET=1 python -m numba.runtests -- numba.tests.test_openmp.TestOpenmpTarget \
|| { echo "Test Numba PyOMP Target GPU failed"; exit 1; }
fi

if [[ "${machine}" == "ruby" ]]; then
echo "=> Test Numba PyOMP Target Host device(1)"
TEST_DEVICES=1 RUN_TARGET=1 python -m numba.runtests -- numba.tests.test_openmp.TestOpenmpTarget \
|| { echo "Test Numba PyOMP Target Host failed"; exit 1; }
fi
# TODO: Enable once we fix codegen in the backend.
#if [[ "${machine}" == "ruby" ]]; then
# echo "=> Test Numba PyOMP Target Host device(1)"
# TEST_DEVICES=1 RUN_TARGET=1 python -m numba.runtests -- numba.tests.test_openmp.TestOpenmpTarget \
# || { echo "Test Numba PyOMP Target Host failed"; exit 1; }
#fi

popd
103 changes: 34 additions & 69 deletions numba/openmp.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,53 +50,36 @@
import types as python_types
import numba

llvm_binpath=None
llvm_libpath=None
def _init():
global llvm_binpath
global llvm_libpath

if config.DEBUG_OPENMP_LLVM_PASS >= 1:
ll.set_option('openmp', '-debug')
ll.set_option('openmp', '-debug-only=intrinsics-openmp')

library_missing = False

numba_openmp_path = os.path.dirname(os.path.realpath(__file__))
numba_openmp_lib_path = numba_openmp_path + "/lib"
numba_openmp_bin_path = numba_openmp_path + "/bin"

iomplib = os.getenv('NUMBA_OMP_LIB',None)
if iomplib is None:
lib_name = numba_openmp_lib_path + "/libomp.so"
if os.path.isfile(lib_name):
iomplib = lib_name
if iomplib is None:
iomplib = ctypes.util.find_library("libomp.so")
if iomplib is None:
iomplib = ctypes.util.find_library("libiomp5.so")
if iomplib is None:
iomplib = ctypes.util.find_library("omp")
if iomplib is None:
iomplib = ctypes.util.find_library("libomp")
if iomplib is None:
library_missing = True
else:
sys_platform = sys.platform

llvm_version = subprocess.check_output(['llvm-config', '--version']).decode().strip()
if llvm_version != "14.0.6":
raise RuntimeError(f"Incompatible LLVM version {llvm_version}, PyOMP expects LLVM 14.0.6")

llvm_binpath = subprocess.check_output(['llvm-config', '--bindir']).decode().strip()
llvm_libpath = subprocess.check_output(['llvm-config', '--libdir']).decode().strip()
iomplib = llvm_libpath + "/libomp" + (".dylib" if sys_platform == "darwin" else ".so")
if config.DEBUG_OPENMP >= 1:
print("Found OpenMP runtime library at", iomplib)
ll.load_library_permanently(iomplib)

omptargetlib = os.getenv('NUMBA_OMPTARGET_LIB', None)
if omptargetlib is None:
lib_name = numba_openmp_lib_path + "/libomptarget.so"
if os.path.isfile(lib_name):
omptargetlib = lib_name
if omptargetlib is None:
omptargetlib = ctypes.util.find_library("libomptarget.so")
if omptargetlib is None:
omptargetlib = ctypes.util.find_library("omptarget")
if omptargetlib is None:
library_missing = True
else:
# libomptarget is unavailable on apple, windows, so return.
if sys_platform.startswith("darwin") or sys_platform.startswith("win32"):
return

omptargetlib = llvm_libpath + "/libomptarget.so"
if config.DEBUG_OPENMP >= 1:
print("Found OpenMP target runtime library at", omptargetlib)
ll.load_library_permanently(omptargetlib)

_init()

#----------------------------------------------------------------------------------------------

class NameSlice:
Expand Down Expand Up @@ -2083,7 +2066,7 @@ def __init__(self):
self.libdevice_path = cudalibs.get_libdevice()
with open(self.libdevice_path, "rb") as f:
self.libs_mod = ll.parse_bitcode(f.read())
self.libomptarget_arch = numba_openmp_lib_path + \
self.libomptarget_arch = llvm_libpath + \
'/libomptarget-new-nvptx-' + self.sm + '.bc'
with open(self.libomptarget_arch, "rb") as f:
libomptarget_mod = ll.parse_bitcode(f.read())
Expand Down Expand Up @@ -2181,25 +2164,27 @@ def _get_target_image_toolchain(self, mod, filename_prefix):
with open(filename_prefix + '.ll', 'w') as f:
f.write(str(mod))

if config.DEBUG_OPENMP_LLVM_PASS >= 1:
cmd_list = [numba_openmp_bin_path + '/opt', '-S', '--intrinsics-openmp', '-debug-only=intrinsics-openmp',
filename_prefix + '.ll', '-o', filename_prefix + '-intrinsics_omp.ll']
else:
cmd_list = [numba_openmp_bin_path + '/opt', '-S', '--intrinsics-openmp',
filename_prefix + '.ll', '-o', filename_prefix + '-intrinsics_omp.ll']
subprocess.run(cmd_list, check=True)
# Lower openmp intrinsics.
with ll.create_module_pass_manager() as pm:
pm.add_intrinsics_openmp_pass()
pm.add_cfg_simplification_pass()
pm.run(mod)

with open(filename_prefix + '-intrinsics_omp.ll', 'w') as f:
f.write(str(mod))

if config.DEBUG_OPENMP >= 1:
print('libomptarget_arch', self.libomptarget_arch)
subprocess.run([numba_openmp_bin_path + '/llvm-link',
subprocess.run([llvm_binpath + '/llvm-link',
'--suppress-warnings',
'--internalize', '-S', filename_prefix +
'-intrinsics_omp.ll', self.libomptarget_arch, self.libdevice_path,
'-o', filename_prefix + '-intrinsics_omp-linked.ll'],
check=True)
subprocess.run([numba_openmp_bin_path + '/opt', '-S', '-O3', filename_prefix + '-intrinsics_omp-linked.ll',
subprocess.run([llvm_binpath + '/opt', '-S', '-O3', filename_prefix + '-intrinsics_omp-linked.ll',
'-o', filename_prefix + '-intrinsics_omp-linked-opt.ll'], check=True)

subprocess.run([numba_openmp_bin_path + '/llc', '-O3', '-march=nvptx64', f'-mcpu={self.sm}', f'-mattr=+ptx64,+{self.sm}',
subprocess.run([llvm_binpath + '/llc', '-O3', '-march=nvptx64', f'-mcpu={self.sm}', f'-mattr=+ptx64,+{self.sm}',
filename_prefix + '-intrinsics_omp-linked-opt.ll',
'-o', filename_prefix + '-intrinsics_omp-linked-opt.s'], check=True)

Expand Down Expand Up @@ -6216,26 +6201,6 @@ def _add_openmp_ir_nodes(func_ir, blocks, blk_start, blk_end, body_blocks, extra
openmp ir nodes in it and adds the ending openmp ir nodes to
the end block.
"""
# First check for presence of required libraries.
if library_missing:
if iomplib is None:
print("OpenMP runtime library could not be found.")
print("Make sure that libomp.so or libiomp5.so is in your library path or")
print("specify the location of the OpenMP runtime library with the")
print("NUMBA_OMP_LIB environment variables.")
sys.exit(-1)

if omptargetlib is None:
if sys.platform.startswith("darwin"):
# OpenMP GPU offloading is unavailable on Darwin
pass
else:
print("OpenMP target runtime library could not be found.")
print("Make sure that libomptarget.so or")
print("specify the location of the OpenMP runtime library with the")
print("NUMBA_OMPTARGET_LIB environment variables.")
sys.exit(-1)

sblk = blocks[blk_start]
scope = sblk.scope
loc = sblk.loc
Expand Down
25 changes: 13 additions & 12 deletions numba/tests/test_openmp.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
# process starts which enables the tests within the process. The decorator
# @needs_subprocess is used to ensure the appropriate test skips are made.

#@linux_only
#
#class TestOpenmpRunner(TestCase):
# _numba_parallel_test_ = False
#
Expand Down Expand Up @@ -323,7 +323,7 @@ def __init__(self, typingctx, targetctx, args, test_ir):
self.state.metadata = {}


#@linux_only
#
#class TestOpenmpBasic(TestOpenmpBase):
# """OpenMP smoke tests. These tests check the most basic
# functionality"""
Expand All @@ -332,7 +332,7 @@ def __init__(self, typingctx, targetctx, args, test_ir):
# TestOpenmpBase.__init__(self, *args)


@linux_only

class TestOpenmpRoutinesEnvVariables(TestOpenmpBase):
MAX_THREADS = 5

Expand Down Expand Up @@ -551,7 +551,7 @@ def test_impl(N, c):
np.testing.assert_array_equal(r[0], r[1])


@linux_only

class TestOpenmpParallelForResults(TestOpenmpBase):

def __init__(self, *args):
Expand Down Expand Up @@ -702,7 +702,7 @@ def test_impl(n1, n2, n3):
np.testing.assert_equal(ja[a1i][a2i], ka[a1i][a2i])


@linux_only

class TestOpenmpWorksharingSchedule(TestOpenmpBase):

def __init__(self, *args):
Expand Down Expand Up @@ -861,7 +861,7 @@ def test_impl(nt, c, cs):
assert(ca[-2] >= cs)


@linux_only

class TestOpenmpParallelClauses(TestOpenmpBase):

def __init__(self, *args):
Expand Down Expand Up @@ -997,7 +997,7 @@ def test_impl():
self.check(test_impl)


@linux_only

class TestOpenmpDataClauses(TestOpenmpBase):

def __init__(self, *args):
Expand Down Expand Up @@ -1446,7 +1446,7 @@ def test_impl(N):
assert(r[1] == N//2-1)


@linux_only

class TestOpenmpConstraints(TestOpenmpBase):
"""Tests designed to confirm that errors occur when expected, or
to see how OpenMP behaves in various circumstances"""
Expand Down Expand Up @@ -1655,7 +1655,7 @@ def test_impl():
test_impl()


@linux_only

class TestOpenmpConcurrency(TestOpenmpBase):

def __init__(self, *args):
Expand Down Expand Up @@ -2082,7 +2082,7 @@ def test_impl(N):
for i in range(N):
np.testing.assert_array_equal(r[i], np.array([1, 2]))

@linux_only

class TestOpenmpTask(TestOpenmpBase):

def __init__(self, *args):
Expand Down Expand Up @@ -2507,7 +2507,7 @@ def test_impl(mode):
self.check(test_impl, 2)


@linux_only

@unittest.skipUnless(TestOpenmpBase.skip_disabled, "Unimplemented")
class TestOpenmpTaskloop(TestOpenmpBase):

Expand Down Expand Up @@ -2596,6 +2596,7 @@ def test_impl(ntsks, nt):
np.testing.assert_array_equal(r[1], r[2])



@linux_only
@unittest.skipUnless(TestOpenmpBase.skip_disabled or
TestOpenmpBase.run_target, "Unimplemented")
Expand Down Expand Up @@ -3893,7 +3894,7 @@ def func_with_subtest(self):
return func_with_subtest
setattr(TestOpenmpTarget, "test_" + test_func.__name__, make_func_with_subtest(test_func))

@linux_only

class TestOpenmpPi(TestOpenmpBase):

def __init__(self, *args):
Expand Down
2 changes: 0 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -442,8 +442,6 @@ def check_file_at_path(path2file):
"numba.misc": ["cmdlang.gdb"],
"numba.typed": ["py.typed"],
"numba.cuda" : ["cpp_function_wrappers.cu"],
"numba.lib" : ["numba/lib/*.bc", "numba/lib/lib*omp*so"],
"numba.bin" : ["numba/bin/opt", "numba/bin/llc", "numba/bin/llvm-link", "numba/bin/clang"]
},
scripts=["bin/numba"],
url="https://numba.pydata.org",
Expand Down