Skip to content

Commit d1ab94c

Browse files
authored
Add compatibility for NumPy 2.0 (microsoft#21085)
### Description As suggested by SciPy's doc, we will `Build against NumPy 2.0.0, then it will work for all NumPy versions with the same major version number (NumPy does maintain backwards ABI compatibility), and as far back as NumPy 1.19 series at the time of writing` I think it works because in [numpyconfig.h#L64](https://github.com/numpy/numpy/blob/main/numpy/_core/include/numpy/numpyconfig.h#L64) there is a macro NPY_FEATURE_VERSION. By default it is set to NPY_1_19_API_VERSION. And the NPY_FEATURE_VERSION macro controls ABI. This PR only upgrade the build time dependency; When a user installs ONNX Runtime, they still can use numpy 1.x. ### Motivation and Context Recently numpy published a new version, 2.0.0, which is incompatible with the latest ONNX Runtime release.
1 parent 78316c8 commit d1ab94c

File tree

22 files changed

+56
-113
lines changed

22 files changed

+56
-113
lines changed

cmake/CMakeLists.txt

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,10 @@ if (onnxruntime_BUILD_SHARED_LIB OR onnxruntime_ENABLE_PYTHON)
579579
else()
580580
find_package(Python 3.8 COMPONENTS Interpreter Development.Module NumPy)
581581
endif()
582+
message("Numpy version: ${Python_NumPy_VERSION}")
583+
if(Python_NumPy_VERSION VERSION_LESS "2.0.0")
584+
message(WARNING "The build binary will not be compatible with NumPy 2.0 because the NumPy installed on this machine is too low.")
585+
endif()
582586
else()
583587
find_package(Python 3.8 COMPONENTS Interpreter)
584588
endif()
@@ -1406,14 +1410,6 @@ string(APPEND ORT_BUILD_INFO "build type=${CMAKE_BUILD_TYPE}")
14061410
string(APPEND ORT_BUILD_INFO ", cmake cxx flags: ${CMAKE_CXX_FLAGS}")
14071411
configure_file(onnxruntime_config.h.in ${CMAKE_CURRENT_BINARY_DIR}/onnxruntime_config.h)
14081412
get_property(onnxruntime_GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
1409-
if (onnxruntime_GENERATOR_IS_MULTI_CONFIG)
1410-
configure_file(../requirements.txt.in ${CMAKE_CURRENT_BINARY_DIR}/Debug/requirements.txt)
1411-
configure_file(../requirements.txt.in ${CMAKE_CURRENT_BINARY_DIR}/Release/requirements.txt)
1412-
configure_file(../requirements.txt.in ${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/requirements.txt)
1413-
configure_file(../requirements.txt.in ${CMAKE_CURRENT_BINARY_DIR}/MinSizeRel/requirements.txt)
1414-
else()
1415-
configure_file(../requirements.txt.in ${CMAKE_CURRENT_BINARY_DIR}/requirements.txt)
1416-
endif()
14171413

14181414
if (onnxruntime_USE_CUDA)
14191415
set(CMAKE_CUDA_RUNTIME_LIBRARY Shared)

cmake/onnxruntime_python.cmake

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,9 @@ add_custom_command(
562562
COMMAND ${CMAKE_COMMAND} -E copy
563563
${ONNXRUNTIME_ROOT}/__init__.py
564564
$<TARGET_FILE_DIR:${build_output_target}>/onnxruntime/
565+
COMMAND ${CMAKE_COMMAND} -E copy
566+
${REPO_ROOT}/requirements.txt
567+
$<TARGET_FILE_DIR:${build_output_target}>
565568
COMMAND ${CMAKE_COMMAND} -E copy
566569
${REPO_ROOT}/ThirdPartyNotices.txt
567570
$<TARGET_FILE_DIR:${build_output_target}>/onnxruntime/

onnxruntime/test/onnx/gen_test_models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ def test_abs(output_dir):
144144
)
145145
generate_abs_op_test(
146146
TensorProto.UINT16,
147-
np.uint16([-32767, -4, 0, 3, 32767]),
147+
np.uint16([0, 3, 32767, 65535]),
148148
os.path.join(output_dir, "test_abs_uint16"),
149149
)
150150
generate_abs_op_test(

onnxruntime/test/python/quantization/test_quant_util.py

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,41 +37,45 @@ def _compute_scale_zp(rmin, rmax, qmin, qmax, qtype, symmetric=False, min_real_r
3737
assert isinstance(scale, numpy.ndarray)
3838
return [float(zp), float(scale)]
3939

40-
self.assertEqual(_compute_scale_zp(0.0, 0.0, -127, 127, numpy.int8, symmetric=True), [0, 1.0])
41-
self.assertEqual(_compute_scale_zp(1.0, -1.0, -127, 127, numpy.int8, symmetric=True), [0, 1.0])
42-
self.assertEqual(_compute_scale_zp(0.0, 0.0, 0, 255, numpy.uint8, symmetric=True), [0, 1.0])
43-
self.assertEqual(_compute_scale_zp(1.0, -1.0, 0, 255, numpy.uint8, symmetric=True), [0, 1.0])
40+
numpy.testing.assert_allclose(_compute_scale_zp(0.0, 0.0, -127, 127, numpy.int8, symmetric=True), [0, 1.0])
41+
numpy.testing.assert_allclose(_compute_scale_zp(1.0, -1.0, -127, 127, numpy.int8, symmetric=True), [0, 1.0])
42+
numpy.testing.assert_allclose(_compute_scale_zp(0.0, 0.0, 0, 255, numpy.uint8, symmetric=True), [0, 1.0])
43+
numpy.testing.assert_allclose(_compute_scale_zp(1.0, -1.0, 0, 255, numpy.uint8, symmetric=True), [0, 1.0])
4444

45-
self.assertEqual(
45+
numpy.testing.assert_allclose(
4646
_compute_scale_zp(-1.0, 2.0, -127, 127, numpy.int8, symmetric=True), [0, numpy.float32(2.0 / 127)]
4747
)
48-
self.assertEqual(
48+
numpy.testing.assert_allclose(
4949
_compute_scale_zp(-1.0, 2.0, -127, 127, numpy.int8, symmetric=False), [-42, numpy.float32(3.0 / 254)]
5050
)
5151

52-
self.assertEqual(
52+
numpy.testing.assert_allclose(
5353
_compute_scale_zp(-1.0, 2.0, 0, 255, numpy.uint8, symmetric=True), [128, numpy.float32(4.0 / 255)]
5454
)
55-
self.assertEqual(
55+
numpy.testing.assert_allclose(
5656
_compute_scale_zp(-1.0, 2.0, 0, 255, numpy.uint8, symmetric=False), [85, numpy.float32(3.0 / 255)]
5757
)
5858

5959
tiny_float = numpy.float32(numpy.finfo(numpy.float32).tiny * 0.1)
60-
self.assertEqual(_compute_scale_zp(-tiny_float, tiny_float, 0, 255, numpy.uint8, symmetric=True), [0, 1.0])
61-
self.assertEqual(_compute_scale_zp(-tiny_float, 0.0, 0, 255, numpy.uint8, symmetric=False), [0, 1.0])
60+
numpy.testing.assert_allclose(
61+
_compute_scale_zp(-tiny_float, tiny_float, 0, 255, numpy.uint8, symmetric=True), [0, 1.0]
62+
)
63+
numpy.testing.assert_allclose(
64+
_compute_scale_zp(-tiny_float, 0.0, 0, 255, numpy.uint8, symmetric=False), [0, 1.0]
65+
)
6266

6367
# Test enforcing a minimum floatint-point range.
64-
self.assertEqual(
68+
numpy.testing.assert_allclose(
6569
_compute_scale_zp(0.0, 0.0, 0, 255, numpy.uint8, symmetric=False, min_real_range=0.0001), [0, 0.0001 / 255]
6670
)
67-
self.assertEqual(
71+
numpy.testing.assert_allclose(
6872
_compute_scale_zp(0.0, 0.0, -128, 127, numpy.int8, symmetric=True, min_real_range=0.0001), [0, 0.0002 / 255]
6973
)
70-
self.assertEqual(
74+
numpy.testing.assert_allclose(
7175
_compute_scale_zp(0.0, 0.0, 0, 65535, numpy.uint16, symmetric=False, min_real_range=0.0001),
7276
[0, 0.0001 / 65535],
7377
)
74-
self.assertEqual(
78+
numpy.testing.assert_allclose(
7579
_compute_scale_zp(0.0, 0.0, -32768, 32767, numpy.int16, symmetric=True, min_real_range=0.0001),
7680
[0, 0.0002 / 65535],
7781
)

onnxruntime/test/python/quantization/test_quantizeblockwise_bnb4.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ def quantize_blockwise_bnb4_ref(matrix_float: npt.ArrayLike, block_size: int, qu
8787
absmax[block_idx] = block_absmax
8888

8989
if block_len % 2 != 0:
90-
block = np.append(block, 0.0)
90+
block = np.append(block, np.float32(0.0))
9191
block_len += 1
9292

9393
block *= reciprocal_absmax
@@ -131,8 +131,8 @@ def test_quantize_blockwise_bnb4(self):
131131
matrix_float = np.random.uniform(-1, 1, (k, n)).astype(type)
132132
quant_value_ref, absmax_ref = quantize_blockwise_bnb4_ref(matrix_float, block_size, quant_type)
133133
quant_value, absmax = quantize_blockwise_bnb4_target(matrix_float, block_size, quant_type)
134-
assert np.allclose(quant_value_ref, quant_value)
135-
assert np.allclose(absmax_ref, absmax)
134+
np.testing.assert_allclose(quant_value_ref, quant_value)
135+
np.testing.assert_allclose(absmax_ref, absmax)
136136

137137

138138
if __name__ == "__main__":
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
coloredlogs
22
flatbuffers
3-
numpy >= @Python_NumPy_VERSION@
3+
numpy >= 1.21.6
44
packaging
55
protobuf
66
sympy

tools/ci_build/github/azure-pipelines/templates/py-packaging-selectable-stage.yml

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -152,17 +152,6 @@ stages:
152152
filename: 'C:\Program Files\Intel\openvino_2021.4.752\bin\setupvars.bat'
153153
modifyEnvironment: true
154154

155-
- task: PythonScript@0
156-
inputs:
157-
scriptSource: inline
158-
script: |
159-
import sys
160-
np_version = 'numpy==1.21.6' if sys.version_info < (3, 11) else 'numpy==1.24.2'
161-
import subprocess
162-
subprocess.call(['pip', 'install', '-q', 'setuptools', 'wheel', np_version])
163-
workingDirectory: '$(Build.BinariesDirectory)'
164-
displayName: 'Install python modules'
165-
166155
- task: PowerShell@2
167156
displayName: 'Install ONNX'
168157
inputs:
@@ -419,17 +408,6 @@ stages:
419408
modifyEnvironment: true
420409
workingFolder: '$(Build.BinariesDirectory)'
421410

422-
- task: PythonScript@0
423-
inputs:
424-
scriptSource: inline
425-
script: |
426-
import sys
427-
np_version = 'numpy==1.21.6' if sys.version_info < (3, 11) else 'numpy==1.24.2'
428-
import subprocess
429-
subprocess.call(['pip', 'install', '-q', 'setuptools', 'wheel', np_version])
430-
workingDirectory: '$(Build.BinariesDirectory)'
431-
displayName: 'Install python modules'
432-
433411
- task: PowerShell@2
434412
displayName: 'Install ONNX'
435413
inputs:

tools/ci_build/github/azure-pipelines/templates/py-packaging-stage.yml

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -153,17 +153,6 @@ stages:
153153
modifyEnvironment: true
154154
workingFolder: '$(Build.BinariesDirectory)'
155155

156-
- task: PythonScript@0
157-
inputs:
158-
scriptSource: inline
159-
script: |
160-
import sys
161-
np_version = 'numpy==1.21.6' if sys.version_info < (3, 11) else 'numpy==1.24.2'
162-
import subprocess
163-
subprocess.call(['pip', 'install', '-q', 'setuptools', 'wheel', np_version])
164-
workingDirectory: '$(Build.BinariesDirectory)'
165-
displayName: 'Install python modules'
166-
167156
- template: download-deps.yml
168157

169158
- task: PythonScript@0

tools/ci_build/github/azure-pipelines/templates/py-win-gpu.yml

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -89,20 +89,6 @@ stages:
8989
tsaConfigFilePath: '$(Build.SourcesDirectory)\.config\tsaoptions.json'
9090
appendSourceBranchName: false
9191

92-
- task: PythonScript@0
93-
inputs:
94-
scriptSource: inline
95-
script: |
96-
import sys
97-
np_version = 'numpy==1.21.6' if sys.version_info < (3, 11) else 'numpy==1.26'
98-
import subprocess
99-
try:
100-
subprocess.check_call(['pip', 'install', '-q', 'setuptools', 'wheel', np_version])
101-
except subprocess.CalledProcessError:
102-
sys.exit(1)
103-
workingDirectory: '$(Build.BinariesDirectory)'
104-
displayName: 'Install python modules'
105-
10692
- template: download-deps.yml
10793

10894
- ${{ if ne(parameters.ENV_SETUP_SCRIPT, '') }}:

tools/ci_build/github/azure-pipelines/templates/py-win-x64-qnn.yml

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -60,17 +60,6 @@ jobs:
6060
tsaConfigFilePath: '$(Build.SourcesDirectory)\.config\tsaoptions.json'
6161
appendSourceBranchName: false
6262

63-
- task: PythonScript@0
64-
inputs:
65-
scriptSource: inline
66-
script: |
67-
import sys
68-
np_version = 'numpy==1.21.6' if sys.version_info < (3, 11) else 'numpy==1.24.2'
69-
import subprocess
70-
subprocess.call(['pip', 'install', '-q', 'setuptools', 'wheel', np_version])
71-
workingDirectory: '$(Build.BinariesDirectory)'
72-
displayName: 'Install python modules'
73-
7463
- template: download-deps.yml
7564

7665
- task: PythonScript@0

0 commit comments

Comments
 (0)