Add compatibility for NumPy 2.0 (#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.
This commit is contained in:
Changming Sun 2024-06-27 13:50:53 -07:00 committed by GitHub
parent 78316c8cbe
commit d1ab94c2b0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 56 additions and 113 deletions

View file

@ -579,6 +579,10 @@ if (onnxruntime_BUILD_SHARED_LIB OR onnxruntime_ENABLE_PYTHON)
else()
find_package(Python 3.8 COMPONENTS Interpreter Development.Module NumPy)
endif()
message("Numpy version: ${Python_NumPy_VERSION}")
if(Python_NumPy_VERSION VERSION_LESS "2.0.0")
message(WARNING "The build binary will not be compatible with NumPy 2.0 because the NumPy installed on this machine is too low.")
endif()
else()
find_package(Python 3.8 COMPONENTS Interpreter)
endif()
@ -1406,14 +1410,6 @@ string(APPEND ORT_BUILD_INFO "build type=${CMAKE_BUILD_TYPE}")
string(APPEND ORT_BUILD_INFO ", cmake cxx flags: ${CMAKE_CXX_FLAGS}")
configure_file(onnxruntime_config.h.in ${CMAKE_CURRENT_BINARY_DIR}/onnxruntime_config.h)
get_property(onnxruntime_GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if (onnxruntime_GENERATOR_IS_MULTI_CONFIG)
configure_file(../requirements.txt.in ${CMAKE_CURRENT_BINARY_DIR}/Debug/requirements.txt)
configure_file(../requirements.txt.in ${CMAKE_CURRENT_BINARY_DIR}/Release/requirements.txt)
configure_file(../requirements.txt.in ${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/requirements.txt)
configure_file(../requirements.txt.in ${CMAKE_CURRENT_BINARY_DIR}/MinSizeRel/requirements.txt)
else()
configure_file(../requirements.txt.in ${CMAKE_CURRENT_BINARY_DIR}/requirements.txt)
endif()
if (onnxruntime_USE_CUDA)
set(CMAKE_CUDA_RUNTIME_LIBRARY Shared)

View file

@ -562,6 +562,9 @@ add_custom_command(
COMMAND ${CMAKE_COMMAND} -E copy
${ONNXRUNTIME_ROOT}/__init__.py
$<TARGET_FILE_DIR:${build_output_target}>/onnxruntime/
COMMAND ${CMAKE_COMMAND} -E copy
${REPO_ROOT}/requirements.txt
$<TARGET_FILE_DIR:${build_output_target}>
COMMAND ${CMAKE_COMMAND} -E copy
${REPO_ROOT}/ThirdPartyNotices.txt
$<TARGET_FILE_DIR:${build_output_target}>/onnxruntime/

View file

@ -144,7 +144,7 @@ def test_abs(output_dir):
)
generate_abs_op_test(
TensorProto.UINT16,
np.uint16([-32767, -4, 0, 3, 32767]),
np.uint16([0, 3, 32767, 65535]),
os.path.join(output_dir, "test_abs_uint16"),
)
generate_abs_op_test(

View file

@ -37,41 +37,45 @@ class TestQuantUtil(unittest.TestCase):
assert isinstance(scale, numpy.ndarray)
return [float(zp), float(scale)]
self.assertEqual(_compute_scale_zp(0.0, 0.0, -127, 127, numpy.int8, symmetric=True), [0, 1.0])
self.assertEqual(_compute_scale_zp(1.0, -1.0, -127, 127, numpy.int8, symmetric=True), [0, 1.0])
self.assertEqual(_compute_scale_zp(0.0, 0.0, 0, 255, numpy.uint8, symmetric=True), [0, 1.0])
self.assertEqual(_compute_scale_zp(1.0, -1.0, 0, 255, numpy.uint8, symmetric=True), [0, 1.0])
numpy.testing.assert_allclose(_compute_scale_zp(0.0, 0.0, -127, 127, numpy.int8, symmetric=True), [0, 1.0])
numpy.testing.assert_allclose(_compute_scale_zp(1.0, -1.0, -127, 127, numpy.int8, symmetric=True), [0, 1.0])
numpy.testing.assert_allclose(_compute_scale_zp(0.0, 0.0, 0, 255, numpy.uint8, symmetric=True), [0, 1.0])
numpy.testing.assert_allclose(_compute_scale_zp(1.0, -1.0, 0, 255, numpy.uint8, symmetric=True), [0, 1.0])
self.assertEqual(
numpy.testing.assert_allclose(
_compute_scale_zp(-1.0, 2.0, -127, 127, numpy.int8, symmetric=True), [0, numpy.float32(2.0 / 127)]
)
self.assertEqual(
numpy.testing.assert_allclose(
_compute_scale_zp(-1.0, 2.0, -127, 127, numpy.int8, symmetric=False), [-42, numpy.float32(3.0 / 254)]
)
self.assertEqual(
numpy.testing.assert_allclose(
_compute_scale_zp(-1.0, 2.0, 0, 255, numpy.uint8, symmetric=True), [128, numpy.float32(4.0 / 255)]
)
self.assertEqual(
numpy.testing.assert_allclose(
_compute_scale_zp(-1.0, 2.0, 0, 255, numpy.uint8, symmetric=False), [85, numpy.float32(3.0 / 255)]
)
tiny_float = numpy.float32(numpy.finfo(numpy.float32).tiny * 0.1)
self.assertEqual(_compute_scale_zp(-tiny_float, tiny_float, 0, 255, numpy.uint8, symmetric=True), [0, 1.0])
self.assertEqual(_compute_scale_zp(-tiny_float, 0.0, 0, 255, numpy.uint8, symmetric=False), [0, 1.0])
numpy.testing.assert_allclose(
_compute_scale_zp(-tiny_float, tiny_float, 0, 255, numpy.uint8, symmetric=True), [0, 1.0]
)
numpy.testing.assert_allclose(
_compute_scale_zp(-tiny_float, 0.0, 0, 255, numpy.uint8, symmetric=False), [0, 1.0]
)
# Test enforcing a minimum floatint-point range.
self.assertEqual(
numpy.testing.assert_allclose(
_compute_scale_zp(0.0, 0.0, 0, 255, numpy.uint8, symmetric=False, min_real_range=0.0001), [0, 0.0001 / 255]
)
self.assertEqual(
numpy.testing.assert_allclose(
_compute_scale_zp(0.0, 0.0, -128, 127, numpy.int8, symmetric=True, min_real_range=0.0001), [0, 0.0002 / 255]
)
self.assertEqual(
numpy.testing.assert_allclose(
_compute_scale_zp(0.0, 0.0, 0, 65535, numpy.uint16, symmetric=False, min_real_range=0.0001),
[0, 0.0001 / 65535],
)
self.assertEqual(
numpy.testing.assert_allclose(
_compute_scale_zp(0.0, 0.0, -32768, 32767, numpy.int16, symmetric=True, min_real_range=0.0001),
[0, 0.0002 / 65535],
)

View file

@ -87,7 +87,7 @@ def quantize_blockwise_bnb4_ref(matrix_float: npt.ArrayLike, block_size: int, qu
absmax[block_idx] = block_absmax
if block_len % 2 != 0:
block = np.append(block, 0.0)
block = np.append(block, np.float32(0.0))
block_len += 1
block *= reciprocal_absmax
@ -131,8 +131,8 @@ class TestQuantizeBlockwiseBnb4(unittest.TestCase):
matrix_float = np.random.uniform(-1, 1, (k, n)).astype(type)
quant_value_ref, absmax_ref = quantize_blockwise_bnb4_ref(matrix_float, block_size, quant_type)
quant_value, absmax = quantize_blockwise_bnb4_target(matrix_float, block_size, quant_type)
assert np.allclose(quant_value_ref, quant_value)
assert np.allclose(absmax_ref, absmax)
np.testing.assert_allclose(quant_value_ref, quant_value)
np.testing.assert_allclose(absmax_ref, absmax)
if __name__ == "__main__":

View file

@ -1,6 +1,6 @@
coloredlogs
flatbuffers
numpy >= @Python_NumPy_VERSION@
numpy >= 1.21.6
packaging
protobuf
sympy

View file

@ -152,17 +152,6 @@ stages:
filename: 'C:\Program Files\Intel\openvino_2021.4.752\bin\setupvars.bat'
modifyEnvironment: true
- task: PythonScript@0
inputs:
scriptSource: inline
script: |
import sys
np_version = 'numpy==1.21.6' if sys.version_info < (3, 11) else 'numpy==1.24.2'
import subprocess
subprocess.call(['pip', 'install', '-q', 'setuptools', 'wheel', np_version])
workingDirectory: '$(Build.BinariesDirectory)'
displayName: 'Install python modules'
- task: PowerShell@2
displayName: 'Install ONNX'
inputs:
@ -419,17 +408,6 @@ stages:
modifyEnvironment: true
workingFolder: '$(Build.BinariesDirectory)'
- task: PythonScript@0
inputs:
scriptSource: inline
script: |
import sys
np_version = 'numpy==1.21.6' if sys.version_info < (3, 11) else 'numpy==1.24.2'
import subprocess
subprocess.call(['pip', 'install', '-q', 'setuptools', 'wheel', np_version])
workingDirectory: '$(Build.BinariesDirectory)'
displayName: 'Install python modules'
- task: PowerShell@2
displayName: 'Install ONNX'
inputs:

View file

@ -153,17 +153,6 @@ stages:
modifyEnvironment: true
workingFolder: '$(Build.BinariesDirectory)'
- task: PythonScript@0
inputs:
scriptSource: inline
script: |
import sys
np_version = 'numpy==1.21.6' if sys.version_info < (3, 11) else 'numpy==1.24.2'
import subprocess
subprocess.call(['pip', 'install', '-q', 'setuptools', 'wheel', np_version])
workingDirectory: '$(Build.BinariesDirectory)'
displayName: 'Install python modules'
- template: download-deps.yml
- task: PythonScript@0

View file

@ -89,20 +89,6 @@ stages:
tsaConfigFilePath: '$(Build.SourcesDirectory)\.config\tsaoptions.json'
appendSourceBranchName: false
- task: PythonScript@0
inputs:
scriptSource: inline
script: |
import sys
np_version = 'numpy==1.21.6' if sys.version_info < (3, 11) else 'numpy==1.26'
import subprocess
try:
subprocess.check_call(['pip', 'install', '-q', 'setuptools', 'wheel', np_version])
except subprocess.CalledProcessError:
sys.exit(1)
workingDirectory: '$(Build.BinariesDirectory)'
displayName: 'Install python modules'
- template: download-deps.yml
- ${{ if ne(parameters.ENV_SETUP_SCRIPT, '') }}:

View file

@ -60,17 +60,6 @@ jobs:
tsaConfigFilePath: '$(Build.SourcesDirectory)\.config\tsaoptions.json'
appendSourceBranchName: false
- task: PythonScript@0
inputs:
scriptSource: inline
script: |
import sys
np_version = 'numpy==1.21.6' if sys.version_info < (3, 11) else 'numpy==1.24.2'
import subprocess
subprocess.call(['pip', 'install', '-q', 'setuptools', 'wheel', np_version])
workingDirectory: '$(Build.BinariesDirectory)'
displayName: 'Install python modules'
- template: download-deps.yml
- task: PythonScript@0

View file

@ -1,6 +1,5 @@
numpy==1.21.6 ; python_version < '3.11'
numpy==1.24.2 ; python_version == '3.11'
numpy==1.26.0 ; python_version >= '3.12'
numpy==1.21.6 ; python_version < '3.9'
numpy==2.0.0 ; python_version >= '3.9'
mypy
pytest
setuptools>=68.2.2

View file

@ -1,6 +1,5 @@
numpy==1.21.6 ; python_version < '3.11'
numpy==1.24.2 ; python_version == '3.11'
numpy==1.26.0 ; python_version >= '3.12'
numpy==1.21.6 ; python_version < '3.9'
numpy==2.0.0 ; python_version >= '3.9'
mypy
pytest
setuptools>=68.2.2

View file

@ -1,6 +1,5 @@
numpy==1.21.6 ; python_version < '3.11'
numpy==1.24.2 ; python_version == '3.11'
numpy==1.26.0 ; python_version >= '3.12'
numpy==1.21.6 ; python_version < '3.9'
numpy==2.0.0 ; python_version >= '3.9'
mypy
pytest
setuptools>=68.2.2

View file

@ -8,7 +8,8 @@ onnx==1.16.1
astunparse
expecttest!=0.2.0
hypothesis
numpy
numpy==1.21.6 ; python_version < '3.9'
numpy==2.0.0 ; python_version >= '3.9'
psutil
pyyaml
requests

View file

@ -1,6 +1,5 @@
numpy==1.21.6 ; python_version < '3.11'
numpy==1.24.2 ; python_version == '3.11'
numpy==1.26.0 ; python_version >= '3.12'
numpy==1.21.6 ; python_version < '3.9'
numpy==2.0.0 ; python_version >= '3.9'
mypy
pytest
setuptools>=68.2.2

View file

@ -1,7 +1,6 @@
cerberus
numpy==1.21.6 ; python_version < '3.11'
numpy==1.24.2 ; python_version == '3.11'
numpy==1.26.0 ; python_version >= '3.12'
numpy==1.24.4 ; python_version < '3.9'
numpy==2.0.0; python_version >= '3.9'
mypy
pytest
setuptools==69.0.3

View file

@ -1,3 +1,2 @@
numpy==1.21.6 ; python_version < '3.11'
numpy==1.24.2 ; python_version == '3.11'
numpy==1.26.0 ; python_version >= '3.12'
numpy==1.21.6 ; python_version < '3.9'
numpy==2.0.0 ; python_version >= '3.9'

View file

@ -5,6 +5,7 @@ setuptools>=68.2.2
cerberus
h5py
scikit-learn
numpy
numpy==1.21.6 ; python_version < '3.9'
numpy==2.0.0 ; python_version >= '3.9'
pandas
parameterized

View file

@ -1,8 +1,7 @@
pandas
scikit-learn
numpy==1.21.6 ; python_version < '3.11'
numpy==1.24.2 ; python_version == '3.11'
numpy==1.26.0 ; python_version >= '3.12'
numpy==1.21.6 ; python_version < '3.9'
numpy==2.0.0 ; python_version >= '3.9'
transformers==v4.36.0
accelerate==0.25.0
rsa==4.9

View file

@ -2,7 +2,7 @@
pip3 install --user --upgrade pip
pip3 install --user numpy==1.19.0 torch pytest
pip3 install --user numpy torch pytest
pip3 install --user /build/Release/dist/*.whl
export PYTHONPATH=/onnxruntime_src/tools:/usr/local/lib/python3.8/site-packages:$PYTHONPATH

View file

@ -1,6 +1,7 @@
setuptools
wheel
numpy
numpy==1.21.6 ; python_version < '3.9'
numpy==2.0.0 ; python_version >= '3.9'
typing_extensions
torch==1.13.1
parameterized

View file

@ -635,16 +635,18 @@ function Install-ONNX {
if ($lastExitCode -ne 0) {
exit $lastExitCode
}
$temp_dir = Get-TempDirectory
$new_requirements_text_file = Join-Path $temp_dir "new_requirements.txt"
Write-Host "Installing python packages..."
[string[]]$pip_args = "-m", "pip", "install", "-qq", "--disable-pip-version-check", "setuptools>=68.2.2", "wheel", "numpy", "protobuf==$protobuf_version"
Get-Content "$src_root\tools\ci_build\github\linux\docker\inference\x86_64\python\cpu\scripts\requirements.txt" | Select-String -pattern 'onnx' -notmatch | Out-File $new_requirements_text_file
[string[]]$pip_args = "-m", "pip", "install", "-qq", "--disable-pip-version-check", "-r", $new_requirements_text_file
&"python.exe" $pip_args
if ($lastExitCode -ne 0) {
exit $lastExitCode
}
$url=Get-DownloadURL -name onnx -src_root $src_root
$temp_dir = Get-TempDirectory
$onnx_src_dir = Join-Path $temp_dir "onnx"
$download_finished = DownloadAndExtract -Uri $url -InstallDirectory $onnx_src_dir -Force
if(-Not $download_finished){