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 коммит произвёл GitHub
Родитель 78316c8cbe
Коммит d1ab94c2b0
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
22 изменённых файлов: 56 добавлений и 113 удалений

Просмотреть файл

@ -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)

Просмотреть файл

@ -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/

Просмотреть файл

@ -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(

Просмотреть файл

@ -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],
)

Просмотреть файл

@ -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__":

Просмотреть файл

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

Просмотреть файл

@ -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:

Просмотреть файл

@ -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

Просмотреть файл

@ -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, '') }}:

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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'

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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){