pyomp 0.5.1__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 (100) hide show
  1. {pyomp-0.5.1 → pyomp-0.5.2}/.github/workflows/build-upload-conda.yml +21 -10
  2. {pyomp-0.5.1 → pyomp-0.5.2}/.github/workflows/build-upload-wheels.yml +78 -4
  3. {pyomp-0.5.1 → pyomp-0.5.2}/PKG-INFO +5 -3
  4. {pyomp-0.5.1 → pyomp-0.5.2}/README.md +3 -1
  5. pyomp-0.5.2/buildscripts/cibuildwheel/setup-miniforge3.sh +63 -0
  6. {pyomp-0.5.1 → 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.1 → pyomp-0.5.2}/buildscripts/conda-recipes/pyomp/meta.yaml +8 -4
  9. pyomp-0.5.2/buildscripts/modal/test_gpu.py +151 -0
  10. {pyomp-0.5.1 → pyomp-0.5.2}/docs/source/installation.rst +3 -1
  11. {pyomp-0.5.1 → pyomp-0.5.2}/pyproject.toml +7 -8
  12. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/__init__.py +12 -0
  13. pyomp-0.5.2/src/numba/openmp/_version.py +24 -0
  14. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/omp_grammar.py +35 -11
  15. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/omp_lower.py +9 -0
  16. pyomp-0.5.2/src/numba/openmp/parser.py +10 -0
  17. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/tests/test_openmp.py +15 -16
  18. {pyomp-0.5.1 → pyomp-0.5.2}/src/pyomp.egg-info/PKG-INFO +5 -3
  19. {pyomp-0.5.1 → pyomp-0.5.2}/src/pyomp.egg-info/SOURCES.txt +5 -7
  20. {pyomp-0.5.1 → pyomp-0.5.2}/src/pyomp.egg-info/requires.txt +1 -1
  21. pyomp-0.5.2/src/pyomp.egg-info/scm_file_list.json +85 -0
  22. pyomp-0.5.2/src/pyomp.egg-info/scm_version.json +8 -0
  23. pyomp-0.5.1/.gitlab/custom-jobs-and-variables.yml +0 -30
  24. pyomp-0.5.1/.gitlab/jobs/tioga.yml +0 -62
  25. pyomp-0.5.1/.gitlab/subscribed-pipelines.yml +0 -43
  26. pyomp-0.5.1/.gitlab-ci.yml +0 -98
  27. pyomp-0.5.1/buildscripts/cibuildwheel/setup-miniconda3.sh +0 -28
  28. pyomp-0.5.1/buildscripts/gitlab/build-and-test.sh +0 -48
  29. pyomp-0.5.1/buildscripts/gitlab/create-conda-pkgs.sh +0 -60
  30. pyomp-0.5.1/src/numba/openmp/_version.py +0 -34
  31. pyomp-0.5.1/src/numba/openmp/parser.py +0 -6
  32. {pyomp-0.5.1 → pyomp-0.5.2}/.github/workflows/build-containers.yml +0 -0
  33. {pyomp-0.5.1 → pyomp-0.5.2}/.gitignore +0 -0
  34. {pyomp-0.5.1 → pyomp-0.5.2}/.gitmodules +0 -0
  35. {pyomp-0.5.1 → pyomp-0.5.2}/.readthedocs.yaml +0 -0
  36. {pyomp-0.5.1 → pyomp-0.5.2}/LICENSE +0 -0
  37. {pyomp-0.5.1 → pyomp-0.5.2}/LICENSE-OPENMP.txt +0 -0
  38. {pyomp-0.5.1 → pyomp-0.5.2}/buildscripts/conda-recipes/pyomp/run_test.sh +0 -0
  39. {pyomp-0.5.1 → pyomp-0.5.2}/buildscripts/containers/Dockerfile +0 -0
  40. {pyomp-0.5.1 → pyomp-0.5.2}/buildscripts/containers/examples/hello.py +0 -0
  41. {pyomp-0.5.1 → pyomp-0.5.2}/buildscripts/containers/examples/pi_loop.py +0 -0
  42. {pyomp-0.5.1 → pyomp-0.5.2}/buildscripts/containers/examples/pi_spmd.py +0 -0
  43. {pyomp-0.5.1 → pyomp-0.5.2}/buildscripts/containers/examples/pi_task.py +0 -0
  44. {pyomp-0.5.1 → pyomp-0.5.2}/docs/Makefile +0 -0
  45. {pyomp-0.5.1 → pyomp-0.5.2}/docs/requirements.txt +0 -0
  46. {pyomp-0.5.1 → pyomp-0.5.2}/docs/source/conf.py +0 -0
  47. {pyomp-0.5.1 → pyomp-0.5.2}/docs/source/index.rst +0 -0
  48. {pyomp-0.5.1 → pyomp-0.5.2}/docs/source/openmp.rst +0 -0
  49. {pyomp-0.5.1 → pyomp-0.5.2}/docs/source/usage.rst +0 -0
  50. {pyomp-0.5.1 → pyomp-0.5.2}/examples/TestDataEnv.py +0 -0
  51. {pyomp-0.5.1 → pyomp-0.5.2}/examples/dgemm_ompGPU.py +0 -0
  52. {pyomp-0.5.1 → pyomp-0.5.2}/examples/hello-target.py +0 -0
  53. {pyomp-0.5.1 → pyomp-0.5.2}/examples/hello.py +0 -0
  54. {pyomp-0.5.1 → pyomp-0.5.2}/examples/piParLoopGPU_BUD.py +0 -0
  55. {pyomp-0.5.1 → pyomp-0.5.2}/examples/piParLoopGPU_BUD_combined.py +0 -0
  56. {pyomp-0.5.1 → pyomp-0.5.2}/examples/piParLoopGPU_loop.py +0 -0
  57. {pyomp-0.5.1 → pyomp-0.5.2}/examples/pi_loop.py +0 -0
  58. {pyomp-0.5.1 → pyomp-0.5.2}/examples/pi_spmd.py +0 -0
  59. {pyomp-0.5.1 → pyomp-0.5.2}/examples/pi_task.py +0 -0
  60. {pyomp-0.5.1 → pyomp-0.5.2}/examples/ploop.1.py +0 -0
  61. {pyomp-0.5.1 → pyomp-0.5.2}/setup.cfg +0 -0
  62. {pyomp-0.5.1 → pyomp-0.5.2}/setup.py +0 -0
  63. {pyomp-0.5.1 → pyomp-0.5.2}/slides/PyOMP_SC24.pdf +0 -0
  64. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/analysis.py +0 -0
  65. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/compiler.py +0 -0
  66. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/config.py +0 -0
  67. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/decorators.py +0 -0
  68. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/exceptions.py +0 -0
  69. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/ir_utils.py +0 -0
  70. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/libs/openmp/patches/14.0.6/0001-BACKPORT-Fix-for-CUDA-OpenMP-RTL.patch +0 -0
  71. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/libs/openmp/patches/14.0.6/0002-Fix-missing-includes.patch +0 -0
  72. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/libs/openmp/patches/14.0.6/0003-Link-static-LLVM-libs.patch +0 -0
  73. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/libs/openmp/patches/15.0.7/0001-Fix-missing-includes.patch +0 -0
  74. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/libs/openmp/patches/15.0.7/0002-Link-LLVM-statically.patch +0 -0
  75. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/libs/openmp/patches/15.0.7/0003-Disable-opaque-pointers-DeviceRTL-bitcode.patch +0 -0
  76. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/libs/openmp/patches/16.0.6/0001-Load-plugins-from-install-directory.patch +0 -0
  77. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/libs/openmp/patches/16.0.6/0002-Link-LLVM-statically.patch +0 -0
  78. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/libs/openmp/patches/20.1.8/0001-Enable-standalone-build.patch +0 -0
  79. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/libs/openmp/patches/20.1.8/0002-Link-statically-LLVM.patch +0 -0
  80. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/libs/openmp/patches/20.1.8/0003-Do-not-build-liboffload.patch +0 -0
  81. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/libs/openmp/patches/20.1.8/0004-Add-getter-for-device-info.patch +0 -0
  82. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/libs/pass/CGIntrinsicsOpenMP.cpp +0 -0
  83. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/libs/pass/CGIntrinsicsOpenMP.h +0 -0
  84. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/libs/pass/CMakeLists.txt +0 -0
  85. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/libs/pass/DebugOpenMP.cpp +0 -0
  86. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/libs/pass/DebugOpenMP.h +0 -0
  87. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/libs/pass/IntrinsicsOpenMP.cpp +0 -0
  88. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/libs/pass/IntrinsicsOpenMP.h +0 -0
  89. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/libs/pass/IntrinsicsOpenMP_CAPI.h +0 -0
  90. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/link_utils.py +0 -0
  91. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/llvm_pass.py +0 -0
  92. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/llvmlite_extensions.py +0 -0
  93. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/offloading.py +0 -0
  94. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/omp_context.py +0 -0
  95. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/omp_ir.py +0 -0
  96. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/omp_runtime.py +0 -0
  97. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/overloads.py +0 -0
  98. {pyomp-0.5.1 → pyomp-0.5.2}/src/numba/openmp/tags.py +0 -0
  99. {pyomp-0.5.1 → pyomp-0.5.2}/src/pyomp.egg-info/dependency_links.txt +0 -0
  100. {pyomp-0.5.1 → 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", "3.14"]
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
@@ -110,9 +132,61 @@ jobs:
110
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.1
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
 
@@ -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
 
@@ -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
@@ -45,22 +45,26 @@ requirements:
45
45
  - sysroot_linux-aarch64 # [aarch64]
46
46
  - setuptools
47
47
  - setuptools_scm
48
- - numba >=0.62, <0.64
48
+ - numba >=0.62, <0.66
49
+ - numba >=0.65, <0.66 # [is_freethreading]
49
50
  - clang {{ LLVM_VERSION }}
50
51
  - clangxx {{ LLVM_VERSION }}
51
52
  - clang-tools {{ LLVM_VERSION }}
52
53
  - llvmdev {{ LLVM_VERSION }}
53
54
  - zlib
54
55
  # require llvm-openmp for the openmp cpu runtime.
55
- - llvm-openmp {{ LLVM_VERSION }}
56
+ - llvm-openmp 21.1.8.* # [osx]
57
+ - llvm-openmp {{ LLVM_VERSION }} # [not osx]
56
58
  - elfutils # [linux]
57
59
  - libffi # [linux]
58
60
  run:
59
61
  - python
60
62
  - setuptools
61
- - numba >=0.62, <0.64
63
+ - numba >=0.62, <0.66
64
+ - numba >=0.65, <0.66 # [is_freethreading]
62
65
  # require llvm-openmp for the openmp cpu runtime.
63
- - llvm-openmp {{ LLVM_VERSION }}
66
+ - llvm-openmp 21.1.8.* # [osx]
67
+ - llvm-openmp {{ LLVM_VERSION }} # [not osx]
64
68
  - lark
65
69
  - cffi
66
70
 
@@ -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()
@@ -24,13 +24,15 @@ supported.
24
24
  +--------+---------------------+
25
25
  | PyOMP | Numba |
26
26
  +========+=====================+
27
- | 0.5.x | 0.62.x - 0.63.x |
27
+ | 0.5.x | 0.62.x - 0.65.x |
28
28
  +--------+---------------------+
29
29
  | 0.4.x | 0.61.x |
30
30
  +--------+---------------------+
31
31
  | 0.3.x | 0.57.x - 0.60.x |
32
32
  +--------+---------------------+
33
33
 
34
+ Python 3.14t (free-threaded) requires Numba 0.65.x.
35
+
34
36
  Additional options
35
37
  ------------------
36
38
 
@@ -17,7 +17,7 @@ classifiers = [
17
17
  "Intended Audience :: Developers",
18
18
  "Topic :: Software Development :: Compilers",
19
19
  ]
20
- dependencies = ["numba>=0.62, <0.64", "lark", "cffi", "setuptools"]
20
+ dependencies = ["numba>=0.62, <0.66", "lark", "cffi", "setuptools"]
21
21
  maintainers = [
22
22
  { name = "Giorgis Georgakoudis", email = "georgakoudis1@llnl.gov" },
23
23
  ]
@@ -42,8 +42,7 @@ archs = ["native"]
42
42
  environment-pass = ["LLVM_VERSION"]
43
43
  # We use miniconda3 to get the clang/llvm toolchain on Linux.
44
44
  before-build = ["rm -rf build dist src/*.egg-info"]
45
- # Skip building 3.14t wheels as they are not supported by the current numba/llvmlite version.
46
- skip = ["*-musllinux_*", "cp38-*", "cp314t-*"]
45
+ skip = ["*-musllinux_*", "cp38-*"]
47
46
  test-command = [
48
47
  # Run host OpenMP tests.
49
48
  "RUN_TARGET=0 python -m numba.runtests -v -- numba.openmp.tests.test_openmp",
@@ -68,15 +67,15 @@ CC = "/usr/bin/clang"
68
67
  CXX = "/usr/bin/clang++"
69
68
 
70
69
  [tool.cibuildwheel.macos]
71
- before-all = ["bash buildscripts/cibuildwheel/setup-miniconda3.sh"]
70
+ before-all = ["bash buildscripts/cibuildwheel/setup-miniforge3.sh"]
72
71
 
73
72
  [tool.cibuildwheel.macos.environment]
74
73
  ENABLE_BUNDLED_LIBOMP = "1"
75
- LLVM_DIR = "${PWD}/_stage/miniconda3/envs/llvmdev-${LLVM_VERSION}/lib/cmake/llvm"
76
- CC = "${PWD}/_stage/miniconda3/envs/llvmdev-${LLVM_VERSION}/bin/clang"
77
- CXX = "${PWD}/_stage/miniconda3/envs/llvmdev-${LLVM_VERSION}/bin/clang++"
74
+ LLVM_DIR = "${PWD}/_stage/miniforge3/envs/llvmdev-${LLVM_VERSION}/lib/cmake/llvm"
75
+ CC = "${PWD}/_stage/miniforge3/envs/llvmdev-${LLVM_VERSION}/bin/clang"
76
+ CXX = "${PWD}/_stage/miniforge3/envs/llvmdev-${LLVM_VERSION}/bin/clang++"
78
77
  # Set the deplioyment target to macOS 11.0.
79
78
  MACOSX_DEPLOYMENT_TARGET = "11.0"
80
79
  # Set the cmake prefix path to find libraries in the conda environment which is
81
80
  # compatible with the macos target.
82
- CMAKE_PREFIX_PATH = "${PWD}/_stage/miniconda3/envs/llvmdev-${LLVM_VERSION}/"
81
+ CMAKE_PREFIX_PATH = "${PWD}/_stage/miniforge3/envs/llvmdev-${LLVM_VERSION}/"
@@ -1,5 +1,17 @@
1
1
  import llvmlite.binding as ll
2
2
  import sys
3
+ import sysconfig
4
+
5
+ import numba
6
+
7
+ # Numba supports free-threaded Python starting with 0.65.
8
+ if sysconfig.get_config_var("Py_GIL_DISABLED") and tuple(
9
+ int(x) for x in numba.__version__.split(".")[:2]
10
+ ) < (0, 65):
11
+ raise ImportError(
12
+ f"PyOMP on free-threaded Python requires numba>=0.65, found {numba.__version__}"
13
+ )
14
+
3
15
  from ._version import version as __version__ # noqa: F401
4
16
 
5
17
  from .config import (
@@ -0,0 +1,24 @@
1
+ # file generated by vcs-versioning
2
+ # don't change, don't track in version control
3
+ from __future__ import annotations
4
+
5
+ __all__ = [
6
+ "__version__",
7
+ "__version_tuple__",
8
+ "version",
9
+ "version_tuple",
10
+ "__commit_id__",
11
+ "commit_id",
12
+ ]
13
+
14
+ version: str
15
+ __version__: str
16
+ __version_tuple__: tuple[int | str, ...]
17
+ version_tuple: tuple[int | str, ...]
18
+ commit_id: str | None
19
+ __commit_id__: str | None
20
+
21
+ __version__ = version = '0.5.2'
22
+ __version_tuple__ = version_tuple = (0, 5, 2)
23
+
24
+ __commit_id__ = commit_id = 'g473dcf5af'
@@ -54,12 +54,41 @@ openmp_grammar = r"""
54
54
  | ordered_construct
55
55
  for_simd_construct: for_simd_directive
56
56
  for_simd_directive: FOR SIMD [for_simd_clause*]
57
- for_simd_clause: for_clause
58
- | simd_clause
57
+ // LALR: avoid ambiguity from overlapping expansions in for_clause vs simd_clause
58
+ for_simd_clause: ORDERED
59
+ | schedule_clause
60
+ | collapse_clause
61
+ | private_clause
62
+ | copyprivate_clause
63
+ | firstprivate_clause
64
+ | lastprivate_clause
65
+ | data_sharing_clause
66
+ | data_default_clause
67
+ | copyin_clause
68
+ | reduction_clause
69
+ | NOWAIT
70
+ | aligned_clause
71
+ | linear_clause
72
+ | uniform_clause
73
+ | inbranch_clause
59
74
  parallel_for_simd_construct: parallel_for_simd_directive
60
75
  parallel_for_simd_directive: PARALLEL FOR SIMD [parallel_for_simd_clause*]
61
- parallel_for_simd_clause: parallel_for_clause
62
- | simd_clause
76
+ // LALR: avoid ambiguity from overlapping expansions in parallel_for_clause vs simd_clause
77
+ parallel_for_simd_clause: if_clause
78
+ | num_threads_clause
79
+ | ORDERED
80
+ | schedule_clause
81
+ | collapse_clause
82
+ | data_default_clause
83
+ | private_clause
84
+ | firstprivate_clause
85
+ | lastprivate_clause
86
+ | data_sharing_clause
87
+ | reduction_clause
88
+ | aligned_clause
89
+ | linear_clause
90
+ | uniform_clause
91
+ | inbranch_clause
63
92
  distribute_construct: distribute_directive
64
93
  distribute_simd_construct: distribute_simd_directive
65
94
  distribute_directive: DISTRIBUTE [distribute_clause*]
@@ -509,10 +538,9 @@ openmp_grammar = r"""
509
538
  | device_clause
510
539
  | if_clause
511
540
  motion_clause: update_motion_type "(" variable_array_section_list ")"
512
- variable_array_section_list: PYTHON_NAME
541
+ // LALR: name_slice already covers bare PYTHON_NAME, so avoid the ambiguous PYTHON_NAME alternatives.
542
+ variable_array_section_list: name_slice
513
543
  // | array_section
514
- | name_slice
515
- | variable_array_section_list "," PYTHON_NAME
516
544
  | variable_array_section_list "," name_slice
517
545
  // | variable_array_section_list "," array_section
518
546
  //array_section: PYTHON_NAME array_section_subscript
@@ -690,7 +718,3 @@ openmp_grammar = r"""
690
718
  %import common.WS
691
719
  %ignore WS
692
720
  """
693
-
694
- """
695
- name_slice: PYTHON_NAME [ "[" slice ["," slice]* "]" ]
696
- """
@@ -2867,6 +2867,15 @@ class OpenmpVisitor(Transformer):
2867
2867
  else:
2868
2868
  return NameSlice(args[0], args[1:])
2869
2869
 
2870
+ def variable_array_section_list(self, args):
2871
+ if DEBUG_OPENMP >= 1:
2872
+ print("visit variable_array_section_list", args, type(args))
2873
+ if len(args) == 1:
2874
+ return args
2875
+ else:
2876
+ args[0].append(args[1])
2877
+ return args[0]
2878
+
2870
2879
  def var_list(self, args):
2871
2880
  if DEBUG_OPENMP >= 1:
2872
2881
  print("visit var_list", args, type(args))