pyomp 0.5.0__tar.gz → 0.5.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. {pyomp-0.5.0 → pyomp-0.5.2}/.github/workflows/build-upload-conda.yml +21 -10
  2. {pyomp-0.5.0 → pyomp-0.5.2}/.github/workflows/build-upload-wheels.yml +80 -6
  3. {pyomp-0.5.0 → pyomp-0.5.2}/PKG-INFO +9 -7
  4. {pyomp-0.5.0 → pyomp-0.5.2}/README.md +7 -5
  5. pyomp-0.5.2/buildscripts/cibuildwheel/setup-miniforge3.sh +63 -0
  6. {pyomp-0.5.0 → pyomp-0.5.2}/buildscripts/conda-recipes/pyomp/conda_build_config.yaml +5 -0
  7. pyomp-0.5.2/buildscripts/conda-recipes/pyomp/freethreading.yaml +4 -0
  8. {pyomp-0.5.0 → pyomp-0.5.2}/buildscripts/conda-recipes/pyomp/meta.yaml +17 -9
  9. {pyomp-0.5.0 → pyomp-0.5.2}/buildscripts/conda-recipes/pyomp/run_test.sh +6 -7
  10. pyomp-0.5.2/buildscripts/modal/test_gpu.py +151 -0
  11. pyomp-0.5.2/docs/requirements.txt +3 -0
  12. pyomp-0.5.2/docs/source/conf.py +62 -0
  13. {pyomp-0.5.0 → pyomp-0.5.2}/docs/source/index.rst +1 -5
  14. pyomp-0.5.2/docs/source/installation.rst +48 -0
  15. pyomp-0.5.2/docs/source/openmp.rst +390 -0
  16. pyomp-0.5.2/docs/source/usage.rst +136 -0
  17. {pyomp-0.5.0 → pyomp-0.5.2}/pyproject.toml +10 -18
  18. pyomp-0.5.2/setup.py +376 -0
  19. pyomp-0.5.2/src/numba/openmp/__init__.py +176 -0
  20. pyomp-0.5.2/src/numba/openmp/_version.py +24 -0
  21. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/compiler.py +13 -15
  22. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/decorators.py +2 -7
  23. pyomp-0.5.2/src/numba/openmp/libs/openmp/patches/20.1.8/0004-Add-getter-for-device-info.patch +182 -0
  24. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/libs/pass/CGIntrinsicsOpenMP.cpp +32 -19
  25. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/libs/pass/CGIntrinsicsOpenMP.h +7 -4
  26. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/libs/pass/DebugOpenMP.h +7 -15
  27. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/libs/pass/IntrinsicsOpenMP.cpp +11 -7
  28. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/llvm_pass.py +4 -0
  29. pyomp-0.5.2/src/numba/openmp/offloading.py +159 -0
  30. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/omp_grammar.py +35 -11
  31. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/omp_ir.py +45 -94
  32. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/omp_lower.py +255 -111
  33. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/omp_runtime.py +1 -11
  34. pyomp-0.5.2/src/numba/openmp/parser.py +10 -0
  35. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/tags.py +0 -125
  36. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/tests/test_openmp.py +263 -387
  37. {pyomp-0.5.0 → pyomp-0.5.2}/src/pyomp.egg-info/PKG-INFO +9 -7
  38. {pyomp-0.5.0 → pyomp-0.5.2}/src/pyomp.egg-info/SOURCES.txt +7 -8
  39. {pyomp-0.5.0 → pyomp-0.5.2}/src/pyomp.egg-info/requires.txt +1 -1
  40. pyomp-0.5.2/src/pyomp.egg-info/scm_file_list.json +85 -0
  41. pyomp-0.5.2/src/pyomp.egg-info/scm_version.json +8 -0
  42. pyomp-0.5.0/.gitlab/custom-jobs-and-variables.yml +0 -30
  43. pyomp-0.5.0/.gitlab/jobs/tioga.yml +0 -62
  44. pyomp-0.5.0/.gitlab/subscribed-pipelines.yml +0 -43
  45. pyomp-0.5.0/.gitlab-ci.yml +0 -98
  46. pyomp-0.5.0/MANIFEST.in +0 -1
  47. pyomp-0.5.0/buildscripts/cibuildwheel/setup-miniconda3.sh +0 -28
  48. pyomp-0.5.0/buildscripts/gitlab/build-and-test.sh +0 -48
  49. pyomp-0.5.0/buildscripts/gitlab/create-conda-pkgs.sh +0 -60
  50. pyomp-0.5.0/docs/requirements.txt +0 -2
  51. pyomp-0.5.0/docs/source/conf.py +0 -44
  52. pyomp-0.5.0/docs/source/installation.rst +0 -15
  53. pyomp-0.5.0/docs/source/openmp.rst +0 -112
  54. pyomp-0.5.0/docs/source/usage.rst +0 -94
  55. pyomp-0.5.0/setup.py +0 -288
  56. pyomp-0.5.0/src/numba/openmp/__init__.py +0 -106
  57. pyomp-0.5.0/src/numba/openmp/_version.py +0 -34
  58. pyomp-0.5.0/src/numba/openmp/parser.py +0 -6
  59. {pyomp-0.5.0 → pyomp-0.5.2}/.github/workflows/build-containers.yml +0 -0
  60. {pyomp-0.5.0 → pyomp-0.5.2}/.gitignore +0 -0
  61. {pyomp-0.5.0 → pyomp-0.5.2}/.gitmodules +0 -0
  62. {pyomp-0.5.0 → pyomp-0.5.2}/.readthedocs.yaml +0 -0
  63. {pyomp-0.5.0 → pyomp-0.5.2}/LICENSE +0 -0
  64. {pyomp-0.5.0 → pyomp-0.5.2}/LICENSE-OPENMP.txt +0 -0
  65. {pyomp-0.5.0 → pyomp-0.5.2}/buildscripts/containers/Dockerfile +0 -0
  66. {pyomp-0.5.0 → pyomp-0.5.2}/buildscripts/containers/examples/hello.py +0 -0
  67. {pyomp-0.5.0 → pyomp-0.5.2}/buildscripts/containers/examples/pi_loop.py +0 -0
  68. {pyomp-0.5.0 → pyomp-0.5.2}/buildscripts/containers/examples/pi_spmd.py +0 -0
  69. {pyomp-0.5.0 → pyomp-0.5.2}/buildscripts/containers/examples/pi_task.py +0 -0
  70. {pyomp-0.5.0 → pyomp-0.5.2}/docs/Makefile +0 -0
  71. {pyomp-0.5.0 → pyomp-0.5.2}/examples/TestDataEnv.py +0 -0
  72. {pyomp-0.5.0 → pyomp-0.5.2}/examples/dgemm_ompGPU.py +0 -0
  73. {pyomp-0.5.0 → pyomp-0.5.2}/examples/hello-target.py +0 -0
  74. {pyomp-0.5.0 → pyomp-0.5.2}/examples/hello.py +0 -0
  75. {pyomp-0.5.0 → pyomp-0.5.2}/examples/piParLoopGPU_BUD.py +0 -0
  76. {pyomp-0.5.0 → pyomp-0.5.2}/examples/piParLoopGPU_BUD_combined.py +0 -0
  77. {pyomp-0.5.0 → pyomp-0.5.2}/examples/piParLoopGPU_loop.py +0 -0
  78. {pyomp-0.5.0 → pyomp-0.5.2}/examples/pi_loop.py +0 -0
  79. {pyomp-0.5.0 → pyomp-0.5.2}/examples/pi_spmd.py +0 -0
  80. {pyomp-0.5.0 → pyomp-0.5.2}/examples/pi_task.py +0 -0
  81. {pyomp-0.5.0 → pyomp-0.5.2}/examples/ploop.1.py +0 -0
  82. {pyomp-0.5.0 → pyomp-0.5.2}/setup.cfg +0 -0
  83. {pyomp-0.5.0 → pyomp-0.5.2}/slides/PyOMP_SC24.pdf +0 -0
  84. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/analysis.py +0 -0
  85. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/config.py +0 -0
  86. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/exceptions.py +0 -0
  87. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/ir_utils.py +0 -0
  88. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/libs/openmp/patches/14.0.6/0001-BACKPORT-Fix-for-CUDA-OpenMP-RTL.patch +0 -0
  89. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/libs/openmp/patches/14.0.6/0002-Fix-missing-includes.patch +0 -0
  90. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/libs/openmp/patches/14.0.6/0003-Link-static-LLVM-libs.patch +0 -0
  91. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/libs/openmp/patches/15.0.7/0001-Fix-missing-includes.patch +0 -0
  92. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/libs/openmp/patches/15.0.7/0002-Link-LLVM-statically.patch +0 -0
  93. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/libs/openmp/patches/15.0.7/0003-Disable-opaque-pointers-DeviceRTL-bitcode.patch +0 -0
  94. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/libs/openmp/patches/16.0.6/0001-Load-plugins-from-install-directory.patch +0 -0
  95. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/libs/openmp/patches/16.0.6/0002-Link-LLVM-statically.patch +0 -0
  96. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/libs/openmp/patches/20.1.8/0001-Enable-standalone-build.patch +0 -0
  97. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/libs/openmp/patches/20.1.8/0002-Link-statically-LLVM.patch +0 -0
  98. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/libs/openmp/patches/20.1.8/0003-Do-not-build-liboffload.patch +0 -0
  99. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/libs/pass/CMakeLists.txt +0 -0
  100. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/libs/pass/DebugOpenMP.cpp +0 -0
  101. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/libs/pass/IntrinsicsOpenMP.h +0 -0
  102. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/libs/pass/IntrinsicsOpenMP_CAPI.h +0 -0
  103. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/link_utils.py +0 -0
  104. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/llvmlite_extensions.py +0 -0
  105. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/omp_context.py +0 -0
  106. {pyomp-0.5.0 → pyomp-0.5.2}/src/numba/openmp/overloads.py +0 -0
  107. {pyomp-0.5.0 → pyomp-0.5.2}/src/pyomp.egg-info/dependency_links.txt +0 -0
  108. {pyomp-0.5.0 → pyomp-0.5.2}/src/pyomp.egg-info/top_level.txt +0 -0
@@ -24,7 +24,7 @@ jobs:
24
24
  matrix:
25
25
  # TODO: Add windows.
26
26
  os: [ubuntu-latest, macos-latest, ubuntu-24.04-arm]
27
- python-version: ["3.10", "3.11", "3.12", "3.13"]
27
+ python-version: ["3.10", "3.11", "3.12", "3.13", "3.14", "3.14t"]
28
28
  steps:
29
29
  - name: Determine conda label
30
30
  run: |
@@ -42,10 +42,14 @@ jobs:
42
42
  with:
43
43
  fetch-depth: 0
44
44
 
45
- - name: Create and activate conda env
46
- uses: conda-incubator/setup-miniconda@fc2d68f6413eb2d87b895e92f8584b5b94a10167
45
+ - name: Setup and activate base conda env
46
+ uses: conda-incubator/setup-miniconda@8ee1f361103df19b6f8c8655fd3967a8ecb162d5 # v4.0.1
47
47
  with:
48
- python-version: "3.12"
48
+ # Keep Conda and conda-build on conda-forge so its build plugin loads.
49
+ miniforge-version: "26.3.2-3"
50
+ conda-remove-defaults: true
51
+ activate-environment: ""
52
+ auto-activate: true
49
53
  auto-update-conda: false
50
54
  show-channel-urls: true
51
55
 
@@ -53,24 +57,31 @@ jobs:
53
57
  # This ensures conda env is active.
54
58
  shell: bash -l {0}
55
59
  run: |
56
- # Setup the anaconda environment.
57
- conda remove --name base conda-anaconda-telemetry
58
- conda install -q -y -c conda-forge conda-build conda-verify anaconda-client
60
+ # Setup the conda-forge environment.
61
+ conda install -n base -q -y --override-channels -c conda-forge conda-build anaconda-client
59
62
  conda config --set anaconda_upload no
63
+ conda build --version
64
+
65
+ # Select the python variant; 3.14t needs the free-threaded ABI.
66
+ if [[ "${{ matrix.python-version }}" == "3.14t" ]]; then
67
+ PY_ARGS=(--python "3.14.* *_cp314t" -m buildscripts/conda-recipes/pyomp/freethreading.yaml)
68
+ else
69
+ PY_ARGS=(--python ${{ matrix.python-version }})
70
+ fi
60
71
 
61
72
  # Build the package.
62
73
  conda build \
63
74
  -c conda-forge \
64
- --python ${{ matrix.python-version }} \
75
+ "${PY_ARGS[@]}" \
65
76
  buildscripts/conda-recipes/pyomp
66
77
 
67
78
  # Get the output file path.
68
79
  OUTPUT=$(conda build -c conda-forge --output \
69
- --python ${{ matrix.python-version }} \
80
+ "${PY_ARGS[@]}" \
70
81
  buildscripts/conda-recipes/pyomp)
71
82
 
72
83
  # Upload the package.
73
- anaconda -t ${{ secrets.ANACONDA_TOKEN }} upload \
84
+ conda run -n base anaconda -t ${{ secrets.ANACONDA_TOKEN }} upload \
74
85
  --user python-for-hpc --label ${{ env.CONDA_LABEL}} \
75
86
  --force "$OUTPUT"
76
87
 
@@ -6,9 +6,20 @@ permissions:
6
6
  on:
7
7
  release:
8
8
  types: [published]
9
+ push:
10
+ branches: [main]
11
+ paths:
12
+ - "buildscripts/cibuildwheel/**"
13
+ - "buildscripts/modal/**"
14
+ - ".github/workflows/build-upload-wheels.yml"
15
+ - "src/**"
16
+ - setup.py
17
+ - MANIFEST.in
18
+ - pyproject.toml
9
19
  pull_request:
10
20
  paths:
11
21
  - "buildscripts/cibuildwheel/**"
22
+ - "buildscripts/modal/**"
12
23
  - ".github/workflows/build-upload-wheels.yml"
13
24
  - "src/**"
14
25
  - setup.py
@@ -73,13 +84,24 @@ jobs:
73
84
  strategy:
74
85
  matrix:
75
86
  os: [ubuntu-latest, macos-latest, ubuntu-24.04-arm]
76
- python-version: ['3.10', '3.11', '3.12', '3.13', '3.14']
77
- numba-version: ['0.62.0', '0.62.1', '0.63.0', '0.63.1']
87
+ python-version: ['3.10', '3.11', '3.12', '3.13', '3.14', '3.14t']
88
+ numba-version: ['0.62.0', '0.62.1', '0.63.0', '0.63.1', '0.64.0', '0.65.0', '0.65.1']
78
89
  exclude:
79
90
  - python-version: '3.14'
80
91
  numba-version: '0.62.0'
81
92
  - python-version: '3.14'
82
93
  numba-version: '0.62.1'
94
+ # Numba supports free-threaded Python starting with 0.65.
95
+ - python-version: '3.14t'
96
+ numba-version: '0.62.0'
97
+ - python-version: '3.14t'
98
+ numba-version: '0.62.1'
99
+ - python-version: '3.14t'
100
+ numba-version: '0.63.0'
101
+ - python-version: '3.14t'
102
+ numba-version: '0.63.1'
103
+ - python-version: '3.14t'
104
+ numba-version: '0.64.0'
83
105
 
84
106
  steps:
85
107
  - name: Download built wheels
@@ -104,15 +126,67 @@ jobs:
104
126
  python -c "import numba; assert numba.__version__ == '${{ matrix.numba-version }}'"
105
127
 
106
128
  # Run host OpenMP tests.
107
- TEST_DEVICES=0 RUN_TARGET=0 python -m numba.runtests -v -- numba.openmp.tests.test_openmp
129
+ RUN_TARGET=0 python -m numba.runtests -v -- numba.openmp.tests.test_openmp
108
130
 
109
131
  # Run device (cpu target) OpenMP tests.
110
- OMP_TARGET_OFFLOAD=mandatory TEST_DEVICES=1 RUN_TARGET=1 \
132
+ OMP_TARGET_OFFLOAD=mandatory TEST_DEVICE=host RUN_TARGET=1 \
111
133
  python -m numba.runtests -v -- numba.openmp.tests.test_openmp.TestOpenmpTarget
112
134
 
135
+ # Test Linux wheels on a real NVIDIA GPU. Fork PRs run after merging to main,
136
+ # where Modal credentials are available to trusted code.
137
+ test-modal-gpu:
138
+ needs: build-wheels
139
+ if: >-
140
+ github.event_name != 'pull_request' ||
141
+ github.event.pull_request.head.repo.full_name == github.repository
142
+ runs-on: ubuntu-latest
143
+ concurrency:
144
+ group: modal-gpu-${{ github.workflow }}-${{ github.ref }}
145
+ cancel-in-progress: true
146
+ env:
147
+ MODAL_TOKEN_ID: ${{ secrets.MODAL_TOKEN_ID }}
148
+ MODAL_TOKEN_SECRET: ${{ secrets.MODAL_TOKEN_SECRET }}
149
+ steps:
150
+ - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5
151
+
152
+ - name: Download Linux wheels
153
+ uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0
154
+ with:
155
+ pattern: cibw-wheels-ubuntu-latest-*
156
+ path: dist
157
+ merge-multiple: true
158
+
159
+ - name: Setup Python
160
+ uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065
161
+ with:
162
+ python-version: "3.12"
163
+
164
+ - name: Validate Modal credentials
165
+ shell: bash
166
+ run: |
167
+ if [[ -z "$MODAL_TOKEN_ID" || -z "$MODAL_TOKEN_SECRET" ]]; then
168
+ echo "::error::MODAL_TOKEN_ID and MODAL_TOKEN_SECRET must be configured"
169
+ exit 1
170
+ fi
171
+
172
+ - name: Run GPU tests on Modal
173
+ run: |
174
+ python -m pip install modal==1.5.3
175
+ set +e
176
+ timeout --signal=TERM --kill-after=30s 20m \
177
+ modal run --timestamps buildscripts/modal/test_gpu.py
178
+ modal_status=$?
179
+ set -e
180
+
181
+ if [[ $modal_status -eq 124 ]]; then
182
+ echo "::error::Modal GPU tests exceeded the 20-minute timeout"
183
+ exit 1
184
+ fi
185
+ exit "$modal_status"
186
+
113
187
  # Only on pre-release: Publish to TestPyPI for testing.
114
188
  publish-testpypi:
115
- needs: [build-wheels, test-wheels, build-sdist]
189
+ needs: [build-wheels, test-wheels, test-modal-gpu, build-sdist]
116
190
  if: github.event.release.prerelease
117
191
  runs-on: ubuntu-latest
118
192
  environment: testpypi
@@ -133,7 +207,7 @@ jobs:
133
207
 
134
208
  # Only on full release: Publish to production PyPI.
135
209
  publish-pypi:
136
- needs: [build-wheels, test-wheels, build-sdist]
210
+ needs: [build-wheels, test-wheels, test-modal-gpu, build-sdist]
137
211
  if: github.event_name == 'release' && !github.event.release.prerelease
138
212
  runs-on: ubuntu-latest
139
213
  environment: pypi
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyomp
3
- Version: 0.5.0
3
+ Version: 0.5.2
4
4
  Summary: Python OpenMP library based on Numba
5
5
  Maintainer-email: Giorgis Georgakoudis <georgakoudis1@llnl.gov>
6
6
  License-Expression: BSD-2-Clause
@@ -15,7 +15,7 @@ Requires-Python: <3.15,>=3.10
15
15
  Description-Content-Type: text/markdown
16
16
  License-File: LICENSE
17
17
  License-File: LICENSE-OPENMP.txt
18
- Requires-Dist: numba<0.64,>=0.62
18
+ Requires-Dist: numba<0.66,>=0.62
19
19
  Requires-Dist: lark
20
20
  Requires-Dist: cffi
21
21
  Requires-Dist: setuptools
@@ -68,10 +68,12 @@ conda install -c python-for-hpc -c conda-forge pyomp
68
68
 
69
69
  | PyOMP | Numba |
70
70
  | ----- | --------------- |
71
- | 0.5.x | 0.62.x - 0.63.x |
71
+ | 0.5.x | 0.62.x - 0.65.x |
72
72
  | 0.4.x | 0.61.x |
73
73
  | 0.3.x | 0.57.x - 0.60.x |
74
74
 
75
+ Python 3.14t (free-threaded) requires Numba 0.65.x.
76
+
75
77
  Besides a standard installation, we also provide the following options to
76
78
  quickly try out PyOMP online or through a container.
77
79
 
@@ -123,10 +125,10 @@ out the [Documentation](https://pyomp.readthedocs.io).
123
125
 
124
126
  PyOMP supports both CPU and GPU programming.
125
127
  For GPU programming, PyOMP implements OpenMP's `target` directive for offloading
126
- and supports the `device` clause, with `device(0)` by convention offloading to a
127
- GPU device.
128
- It is also possible to use the host as a multi-core CPU target device (mainly
129
- for testing purposes) by setting `device(1)`.
128
+ and supports the `device` clause to select the offloading target device.
129
+ For more information see the [GPU
130
+ Offloading](https://pyomp.readthedocs.io/en/latest/openmp.html#openmp-and-gpu-offloading-support)
131
+ section in the documentation.
130
132
 
131
133
  ### Example
132
134
 
@@ -45,10 +45,12 @@ conda install -c python-for-hpc -c conda-forge pyomp
45
45
 
46
46
  | PyOMP | Numba |
47
47
  | ----- | --------------- |
48
- | 0.5.x | 0.62.x - 0.63.x |
48
+ | 0.5.x | 0.62.x - 0.65.x |
49
49
  | 0.4.x | 0.61.x |
50
50
  | 0.3.x | 0.57.x - 0.60.x |
51
51
 
52
+ Python 3.14t (free-threaded) requires Numba 0.65.x.
53
+
52
54
  Besides a standard installation, we also provide the following options to
53
55
  quickly try out PyOMP online or through a container.
54
56
 
@@ -100,10 +102,10 @@ out the [Documentation](https://pyomp.readthedocs.io).
100
102
 
101
103
  PyOMP supports both CPU and GPU programming.
102
104
  For GPU programming, PyOMP implements OpenMP's `target` directive for offloading
103
- and supports the `device` clause, with `device(0)` by convention offloading to a
104
- GPU device.
105
- It is also possible to use the host as a multi-core CPU target device (mainly
106
- for testing purposes) by setting `device(1)`.
105
+ and supports the `device` clause to select the offloading target device.
106
+ For more information see the [GPU
107
+ Offloading](https://pyomp.readthedocs.io/en/latest/openmp.html#openmp-and-gpu-offloading-support)
108
+ section in the documentation.
107
109
 
108
110
  ### Example
109
111
 
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -euxo pipefail
4
+
5
+ MINIFORGE_VERSION="26.3.2-3"
6
+
7
+ # Read LLVM_VERSION from environment and error if not set
8
+ if [ -z "${LLVM_VERSION:-}" ]; then
9
+ echo "Error: LLVM_VERSION environment variable is not set." >&2
10
+ exit 1
11
+ fi
12
+
13
+ if [ "$(uname)" = "Darwin" ]; then
14
+ OS_NAME="MacOSX"
15
+ else
16
+ OS_NAME="Linux"
17
+ fi
18
+ ARCH_NAME="$(uname -m)"
19
+
20
+ case "${OS_NAME}-${ARCH_NAME}" in
21
+ Linux-x86_64)
22
+ MINIFORGE_SHA256="848194851a98903134187fbb4ab50efe87b003e0c0f808f97644b7524a62bf2c"
23
+ ;;
24
+ Linux-aarch64)
25
+ MINIFORGE_SHA256="2c113a69297e612b01ca0f320c22a3107a11f2ab9b573d79ac868a175945ce29"
26
+ ;;
27
+ Linux-ppc64le)
28
+ MINIFORGE_SHA256="df7e80ee070ccc6031e2710eb4cf81ee0012264b587306b5aa3890d3d89edd97"
29
+ ;;
30
+ MacOSX-x86_64)
31
+ MINIFORGE_SHA256="39273e4c89a0a1af4538010615d44ae8f44e1af41007e02def593d20f316b003"
32
+ ;;
33
+ MacOSX-arm64)
34
+ MINIFORGE_SHA256="59168f1e24d0a4ad9932021170809fca836cd240e183eeeb331d5bcfc0098168"
35
+ ;;
36
+ *)
37
+ echo "Unsupported Miniforge platform: ${OS_NAME}-${ARCH_NAME}" >&2
38
+ exit 1
39
+ ;;
40
+ esac
41
+
42
+ echo "Installing Miniforge..."
43
+ MINIFORGE_INSTALLER="Miniforge3-${MINIFORGE_VERSION}-${OS_NAME}-${ARCH_NAME}.sh"
44
+ MINIFORGE_RELEASE_URL="https://github.com/conda-forge/miniforge/releases/download/${MINIFORGE_VERSION}"
45
+ MINIFORGE_URL="${MINIFORGE_RELEASE_URL}/${MINIFORGE_INSTALLER}"
46
+ mkdir -p _downloads
47
+ curl -fsSL "${MINIFORGE_URL}" -o _downloads/miniforge3.sh
48
+ if command -v sha256sum >/dev/null 2>&1; then
49
+ printf '%s %s\n' "${MINIFORGE_SHA256}" _downloads/miniforge3.sh | sha256sum --check -
50
+ elif command -v shasum >/dev/null 2>&1; then
51
+ printf '%s %s\n' "${MINIFORGE_SHA256}" _downloads/miniforge3.sh | shasum -a 256 --check -
52
+ else
53
+ echo "No SHA256 verification command is available" >&2
54
+ exit 1
55
+ fi
56
+ mkdir -p _stage
57
+ bash _downloads/miniforge3.sh -b -f -p "_stage/miniforge3"
58
+ echo "Miniforge installed"
59
+ source "_stage/miniforge3/bin/activate" base
60
+
61
+ # Create conda environment with tools and libraries for the LLVM_VERSION.
62
+ echo "Installing llvmdev ${LLVM_VERSION}..."
63
+ conda create -n llvmdev-${LLVM_VERSION} --override-channels -c conda-forge -q -y clang=${LLVM_VERSION} clangxx=${LLVM_VERSION} clang-tools=${LLVM_VERSION} llvmdev=${LLVM_VERSION} zstd
@@ -1,3 +1,8 @@
1
+ # --- Free-threading ---
2
+ # Default for the is_freethreading selector in meta.yaml; override for 3.14t.
3
+ is_freethreading:
4
+ - false
5
+
1
6
  # --- Compilers ---
2
7
  c_compiler_version:
3
8
  - 9 # [linux]
@@ -0,0 +1,4 @@
1
+ # Variant for free-threaded Python (3.14t) builds, passed with -m. Use this
2
+ # instead of --variants, which `conda build --output` ignores.
3
+ is_freethreading:
4
+ - true
@@ -1,5 +1,7 @@
1
1
  {% set version = environ.get('GIT_DESCRIBE_TAG', '0.0.0').lstrip('v') %}
2
2
  {% set LLVM_VERSION = environ.get('LLVM_VERSION', '20.1.8') %}
3
+ {% set LLVM_VERSION_MAJOR = LLVM_VERSION.split('.')[0] %}
4
+ {% set LLVM_VERSION_MINOR = LLVM_VERSION.split('.')[1] %}
3
5
 
4
6
  package:
5
7
  name: pyomp
@@ -43,32 +45,38 @@ requirements:
43
45
  - sysroot_linux-aarch64 # [aarch64]
44
46
  - setuptools
45
47
  - setuptools_scm
46
- - numba >=0.62, <0.64
48
+ - numba >=0.62, <0.66
49
+ - numba >=0.65, <0.66 # [is_freethreading]
47
50
  - clang {{ LLVM_VERSION }}
48
51
  - clangxx {{ LLVM_VERSION }}
49
52
  - clang-tools {{ LLVM_VERSION }}
50
53
  - llvmdev {{ LLVM_VERSION }}
51
54
  - zlib
52
55
  # require llvm-openmp for the openmp cpu runtime.
53
- - llvm-openmp {{ LLVM_VERSION }}
56
+ - llvm-openmp 21.1.8.* # [osx]
57
+ - llvm-openmp {{ LLVM_VERSION }} # [not osx]
54
58
  - elfutils # [linux]
55
59
  - libffi # [linux]
56
60
  run:
57
61
  - python
58
62
  - setuptools
59
- - numba >=0.62, <0.64
63
+ - numba >=0.62, <0.66
64
+ - numba >=0.65, <0.66 # [is_freethreading]
60
65
  # require llvm-openmp for the openmp cpu runtime.
61
- - llvm-openmp {{ LLVM_VERSION }}
66
+ - llvm-openmp 21.1.8.* # [osx]
67
+ - llvm-openmp {{ LLVM_VERSION }} # [not osx]
62
68
  - lark
63
69
  - cffi
64
70
 
65
71
  test:
66
72
  commands:
67
- - test -f $SP_DIR/numba/openmp/libs/pass/libIntrinsicsOpenMP.dylib # [osx]
68
- - test -f $SP_DIR/numba/openmp/libs/pass/libIntrinsicsOpenMP.so # [linux]
69
- - test -f $SP_DIR/numba/openmp/libs/openmp/lib/libomptarget-amdgpu.bc # [linux]
70
- - test -f $SP_DIR/numba/openmp/libs/openmp/lib/libomptarget-nvptx.bc # [linux]
71
- - test -f $SP_DIR/numba/openmp/libs/openmp/lib/libomptarget.so # [linux]
73
+ - test -f $SP_DIR/numba/openmp/libs/pass/libIntrinsicsOpenMP.dylib # [osx]
74
+ - test -f $SP_DIR/numba/openmp/libs/pass/libIntrinsicsOpenMP.so # [linux]
75
+ - test -f $SP_DIR/numba/openmp/libs/openmp/lib/libomptarget-amdgpu.bc # [linux]
76
+ - test -f $SP_DIR/numba/openmp/libs/openmp/lib/libomptarget-nvptx.bc # [linux]
77
+ - test -f $SP_DIR/numba/openmp/libs/openmp/lib/libomptarget.so.{{ LLVM_VERSION_MAJOR }}.{{ LLVM_VERSION_MINOR }} # [linux]
78
+ - test -f $SP_DIR/numba/openmp/libs/openmp/lib/libpyomp_loader.dylib # [osx]
79
+ - test -f $SP_DIR/numba/openmp/libs/openmp/lib/libpyomp_loader.so # [linux]
72
80
 
73
81
  about:
74
82
  home: https://github.com/Python-for-HPC/PyOMP
@@ -47,20 +47,19 @@ fi
47
47
  # library is inited/de-inited.
48
48
 
49
49
  echo "=> Run OpenMP CPU parallelism tests"
50
- echo "=> Running: TEST_DEVICES=0 RUN_TARGET=0 $SEGVCATCH python -m numba.runtests -v -- numba.openmp.tests.test_openmp"
51
- # TODO: remove requiring the unused TEST_DEVICES.
52
- TEST_DEVICES=0 RUN_TARGET=0 $SEGVCATCH python -m numba.runtests -v -- numba.openmp.tests.test_openmp 2>&1
50
+ echo "=> Running: RUN_TARGET=0 $SEGVCATCH python -m numba.runtests -v -- numba.openmp.tests.test_openmp"
51
+ RUN_TARGET=0 $SEGVCATCH python -m numba.runtests -v -- numba.openmp.tests.test_openmp 2>&1
53
52
 
54
53
  echo "=> Run OpenMP offloading tests on CPU (device 1)"
55
- echo "=> Running: TEST_DEVICES=1 RUN_TARGET=1 $SEGVCATCH python -m numba.runtests -v -- numba.openmp.tests.test_openmp.TestOpenmpTarget"
56
- OMP_TARGET_OFFLOAD=mandatory TEST_DEVICES=1 RUN_TARGET=1 $SEGVCATCH python -m numba.runtests -v -- numba.openmp.tests.test_openmp.TestOpenmpTarget 2>&1
54
+ echo "=> Running: TEST_DEVICE=host RUN_TARGET=1 $SEGVCATCH python -m numba.runtests -v -- numba.openmp.tests.test_openmp.TestOpenmpTarget"
55
+ OMP_TARGET_OFFLOAD=mandatory TEST_DEVICE=host RUN_TARGET=1 $SEGVCATCH python -m numba.runtests -v -- numba.openmp.tests.test_openmp.TestOpenmpTarget 2>&1
57
56
  # Check if NVIDIA GPU is present.
58
57
  if command -v nvidia-smi >/dev/null 2>&1; then
59
58
  # `nvidia-smi --list-gpus` exits non-zero when no GPUs are present; run
60
59
  # it in a conditional so `set -e` does not cause the script to exit.
61
60
  if nvidia-smi --list-gpus >/dev/null 2>&1; then
62
61
  echo "=> Found NVIDIA GPU, Run OpenMP offloading tests on GPU (device 0)"
63
- echo "=> Running: TEST_DEVICES=0 RUN_TARGET=1 $SEGVCATCH python -m numba.runtests -v -- numba.openmp.tests.test_openmp.TestOpenmpTarget"
64
- OMP_TARGET_OFFLOAD=mandatory TEST_DEVICES=0 RUN_TARGET=1 $SEGVCATCH python -m numba.runtests -v -- numba.openmp.tests.test_openmp.TestOpenmpTarget 2>&1
62
+ echo "=> Running: TEST_DEVICE=gpu RUN_TARGET=1 $SEGVCATCH python -m numba.runtests -v -- numba.openmp.tests.test_openmp.TestOpenmpTarget"
63
+ OMP_TARGET_OFFLOAD=mandatory TEST_DEVICE=gpu RUN_TARGET=1 $SEGVCATCH python -m numba.runtests -v -- numba.openmp.tests.test_openmp.TestOpenmpTarget 2>&1
65
64
  fi
66
65
  fi
@@ -0,0 +1,151 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ from pathlib import Path
5
+ import subprocess
6
+
7
+ import modal
8
+
9
+
10
+ PYTHON_VERSIONS = ("3.10", "3.11", "3.12", "3.13", "3.14")
11
+ NUMBA_VERSION = "0.65.1"
12
+ MINIFORGE_VERSION = "26.3.2-3"
13
+ MINIFORGE_SHA256 = "848194851a98903134187fbb4ab50efe87b003e0c0f808f97644b7524a62bf2c"
14
+ WHEEL_DIRECTORY = (
15
+ Path(__file__).resolve().parents[2] / "dist"
16
+ if modal.is_local()
17
+ else Path("/wheels")
18
+ )
19
+ MINIFORGE_PREFIX = "/opt/miniforge3"
20
+
21
+
22
+ def find_linux_wheels() -> dict[str, Path]:
23
+ if not WHEEL_DIRECTORY.is_dir():
24
+ raise RuntimeError(f"Linux wheel directory does not exist: {WHEEL_DIRECTORY}")
25
+
26
+ wheels = {}
27
+ for python_version in PYTHON_VERSIONS:
28
+ abi = python_version.replace(".", "")
29
+ # Match the ABI tag too, so cp314 does not also match cp314t wheels.
30
+ matches = sorted(WHEEL_DIRECTORY.glob(f"*-cp{abi}-cp{abi}-*x86_64.whl"))
31
+ if len(matches) != 1:
32
+ raise RuntimeError(
33
+ f"Expected one cp{abi} Linux x86-64 wheel in {WHEEL_DIRECTORY}, "
34
+ f"found {len(matches)}: {matches}"
35
+ )
36
+ wheels[python_version] = matches[0]
37
+ return wheels
38
+
39
+
40
+ LINUX_WHEELS = find_linux_wheels()
41
+
42
+
43
+ def image_build_commands() -> tuple[list[str], list[str]]:
44
+ environment_commands = []
45
+ wheel_commands = []
46
+ for python_version, wheel in LINUX_WHEELS.items():
47
+ environment = f"py{python_version.replace('.', '')}"
48
+ python = f"{MINIFORGE_PREFIX}/envs/{environment}/bin/python"
49
+ environment_commands.extend(
50
+ [
51
+ (
52
+ f"{MINIFORGE_PREFIX}/bin/conda create -q -y "
53
+ f"--override-channels -c conda-forge -n {environment} "
54
+ f"python={python_version} pip"
55
+ ),
56
+ (
57
+ f"{python} -m pip install "
58
+ f"numba=={NUMBA_VERSION} lark cffi setuptools"
59
+ ),
60
+ (
61
+ f'{python} -c "import numba; '
62
+ f"assert numba.__version__ == '{NUMBA_VERSION}'\""
63
+ ),
64
+ ]
65
+ )
66
+ wheel_commands.append(
67
+ f"{python} -m pip install --no-deps /wheels/{wheel.name}"
68
+ )
69
+ return environment_commands, wheel_commands
70
+
71
+
72
+ ENVIRONMENT_COMMANDS, WHEEL_COMMANDS = image_build_commands()
73
+
74
+
75
+ image = (
76
+ modal.Image.from_registry(
77
+ "nvidia/cuda:12.8.1-devel-ubuntu22.04", add_python="3.12"
78
+ )
79
+ .entrypoint([])
80
+ .apt_install("ca-certificates", "curl")
81
+ .run_commands(
82
+ f"curl -fsSL https://github.com/conda-forge/miniforge/releases/download/"
83
+ f"{MINIFORGE_VERSION}/Miniforge3-{MINIFORGE_VERSION}-Linux-x86_64.sh "
84
+ "-o /tmp/miniforge3.sh",
85
+ f"printf '%s %s\\n' {MINIFORGE_SHA256} /tmp/miniforge3.sh "
86
+ "| sha256sum --check -",
87
+ f"bash /tmp/miniforge3.sh -b -p {MINIFORGE_PREFIX}",
88
+ )
89
+ .run_commands(*ENVIRONMENT_COMMANDS)
90
+ .add_local_dir(WHEEL_DIRECTORY, "/wheels", copy=True)
91
+ .run_commands(*WHEEL_COMMANDS)
92
+ )
93
+
94
+ app = modal.App("pyomp-gpu-ci")
95
+
96
+
97
+ @app.function(
98
+ image=image,
99
+ gpu="T4",
100
+ timeout=60 * 60,
101
+ restrict_modal_access=True,
102
+ single_use_containers=True,
103
+ block_network=True,
104
+ )
105
+ def test_gpu_wheels() -> None:
106
+ subprocess.run(["nvidia-smi", "--list-gpus"], check=True)
107
+
108
+ test_environment = os.environ.copy()
109
+ test_environment.update(
110
+ {
111
+ "NUMBA_DEVELOPER_MODE": "1",
112
+ "NUMBA_DISABLE_ERROR_MESSAGE_HIGHLIGHTING": "1",
113
+ "NUMBA_CAPTURED_ERRORS": "new_style",
114
+ "PYTHONFAULTHANDLER": "1",
115
+ "OMP_TARGET_OFFLOAD": "mandatory",
116
+ "TEST_DEVICE": "gpu",
117
+ "RUN_TARGET": "1",
118
+ }
119
+ )
120
+
121
+ for python_version in PYTHON_VERSIONS:
122
+ environment = f"py{python_version.replace('.', '')}"
123
+ python = f"{MINIFORGE_PREFIX}/envs/{environment}/bin/python"
124
+ print(f"Running GPU tests with Python {python_version} and Numba {NUMBA_VERSION}")
125
+ subprocess.run(
126
+ [
127
+ python,
128
+ "-c",
129
+ "from numba.openmp import print_offloading_info; "
130
+ "print_offloading_info()",
131
+ ],
132
+ check=True,
133
+ env=test_environment,
134
+ )
135
+ subprocess.run(
136
+ [
137
+ python,
138
+ "-m",
139
+ "numba.runtests",
140
+ "-v",
141
+ "--",
142
+ "numba.openmp.tests.test_openmp.TestOpenmpTarget",
143
+ ],
144
+ check=True,
145
+ env=test_environment,
146
+ )
147
+
148
+
149
+ @app.local_entrypoint()
150
+ def main() -> None:
151
+ test_gpu_wheels.remote()
@@ -0,0 +1,3 @@
1
+ sphinx==8.2.3
2
+ sphinx-rtd-theme==3.1.0
3
+ sphinx-copybutton==0.5.2
@@ -0,0 +1,62 @@
1
+ # Configuration file for the Sphinx documentation builder.
2
+
3
+ import os
4
+ import subprocess
5
+ import datetime
6
+
7
+ # -- Project information
8
+
9
+ project = "PyOMP"
10
+ start_year = 2024
11
+ this_year = datetime.datetime.today().year
12
+ copyright_years = (
13
+ str(start_year) if start_year == this_year else f"{start_year}-{this_year}"
14
+ )
15
+ copyright = f"{copyright_years}, PyOMP developers"
16
+ author = "Giorgis Georgakoudis"
17
+
18
+ try:
19
+ # Prefer RTD provided version when available.
20
+ release = os.environ.get("READTHEDOCS_VERSION")
21
+ if not release:
22
+ # Ensure tags are available in shallow or sparse CI clones
23
+ subprocess.run(["git", "fetch", "--tags"], check=False)
24
+ release = (
25
+ subprocess.check_output(["git", "describe", "--tags", "--abbrev=0"])
26
+ .strip()
27
+ .decode()
28
+ )
29
+ except subprocess.CalledProcessError:
30
+ release = os.environ.get("READTHEDOCS_VERSION", "latest")
31
+ version = release
32
+
33
+ # -- General configuration
34
+
35
+ extensions = [
36
+ "sphinx.ext.duration",
37
+ "sphinx.ext.doctest",
38
+ "sphinx.ext.autodoc",
39
+ "sphinx.ext.autosummary",
40
+ "sphinx.ext.intersphinx",
41
+ "sphinx_copybutton",
42
+ ]
43
+
44
+ intersphinx_mapping = {
45
+ "python": ("https://docs.python.org/3/", None),
46
+ "sphinx": ("https://www.sphinx-doc.org/en/master/", None),
47
+ }
48
+ intersphinx_disabled_domains = ["std"]
49
+
50
+ # -- Options for sphinx_copybutton
51
+
52
+ sphinx_copybutton_prompt_text = r">>> |\.\.\. "
53
+ sphinx_copybutton_prompt_is_regexp = True
54
+
55
+ templates_path = ["_templates"]
56
+
57
+ # -- Options for HTML output
58
+
59
+ html_theme = "sphinx_rtd_theme"
60
+
61
+ # -- Options for EPUB output
62
+ epub_show_urls = "footnote"
@@ -1,16 +1,12 @@
1
1
  PyOMP documentation
2
2
  ===================
3
3
 
4
- **PyOMP** implements OpenMP parallel CPU/GPU programming abstraction in Python using Numba.
4
+ **PyOMP** implements OpenMP parallel CPU/GPU programming abstractions in Python using Numba.
5
5
 
6
6
  Check out the :doc:`installation` section for how to install, the :doc:`usage`
7
7
  section on information regarding using PyOMP, and :doc:`openmp` for the list of
8
8
  supported OpenMP abstractions.
9
9
 
10
- .. note::
11
-
12
- This project and its documentation are under active development.
13
-
14
10
  Contents
15
11
  --------
16
12