Unexpected floor division with ndarrays on python 3
- 主要語言
- C++
- 星號
- 537
- 分支
- 223
- 平均合併
- 11 小時 22 分鐘
- 30 天內合併 PR
- 2
描述
Our primarily C++ code base uses an embedded python to do computation with help from `boost::python`. We are in the process of porting to python 3. We have noticed that it appears that the `/` operator when acting on a pair of `boost::python::numpy::ndarray`'s yields floor division. That is to say the results are numerically consistent with constructing the same arrays in a python interpreter and then performing `arr1 // arr2`. We do did not see this behaviour when linking against `python27.dll`. To make my issue concrete I prepared an example based on those provided in the `examples/` folder. It was built on windows 10 using:
- MSVC 2015
- Python 2.7.16
- Python 3.6.8
- cmake 3.16
- Ninja 1.9.0
- Boost 1.70.0
`main.cpp` was:
```cpp
#include
#include
namespace p = boost::python;
namespace np = boost::python::numpy;
typedef float arr_dtype;
int main(int argc, char **argv)
{
Py_Initialize();
np::initialize();
arr_dtype raw_array1[] = {1.53f, 2.53f, 3.53f, 4.53f};
np::ndarray nd_array1 = np::from_data(raw_array1, np::dtype::get_builtin(),
p::make_tuple(4),
p::make_tuple(4),
p::object());
arr_dtype raw_array2[] = {0.1f};
np::ndarray nd_array2 = np::from_data(raw_array2, np::dtype::get_builtin(),
p::make_tuple(1),
p::make_tuple(1),
p::object());
std::cout << "ndarray 1 is " << p::extract(p::str(nd_array1)) << std::endl;
std::cout << "ndarray 2 is " << p::extract(p::str(nd_array2)) << std::endl;
//
p::object result_array_div = nd_array1 / nd_array2;
std::cout << "operator/ division of arrays is " << p::extract(p::str(result_array_div)) << std::endl;
return 0;
}
```
For Python 27 the output when running `main.exe` was consistent with our expectations:
```
ndarray 1 is [1.53 2.53 3.53 4.53]
ndarray 2 is [0.1]
operator/ division of arrays is [15.299999 25.3 35.3 45.300003]
```
For Python 36 the result when running `main.exe` was not consistent with our (possibly misguided) expectations:
```
ndarray 1 is [1.53 2.53 3.53 4.53]
ndarray 2 is [0.1]
operator/ division of arrays is [15. 25. 35. 45.]
```
Is this expected behaviour? Is there any way to enforce non-floor division when using the `/` operator and python 3?
For reference the `CMakeLists.txt` was:
```
cmake_minimum_required(VERSION 3.16)
project(test_boost_numpy_division)
# version selection
if (BUILD_PY3)
set(python_package_name "Python3")
set(BOOST_ROOT "${BOOST_ROOT_PY3}")
set(py_dll_path "${Python3_ROOT_DIR}/python36.dll")
set(py_maj_min_version "36")
else()
set(python_package_name "Python2")
set(BOOST_ROOT "${BOOST_ROOT_PY2}")
set(py_dll_path "C:/Windows/System32/python27.dll")
set(py_maj_min_version "27")
endif()
set(boost_python_module_name "python${py_maj_min_version}")
set(boost_numpy_module_name "numpy${py_maj_min_version}")
# python config
find_package (${python_package_name} COMPONENTS Development REQUIRED)
# boost config
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_LIBS OFF)
find_package(Boost REQUIRED COMPONENTS ${boost_python_module_name} ${boost_numpy_module_name} unit_test_framework)
#
add_executable(main)
target_sources(main PRIVATE main.cpp)
target_link_libraries(main ${python_package_name}::Python)
target_link_libraries(main Boost::${boost_python_module_name} Boost::${boost_numpy_module_name})
set_target_properties( main
PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin"
)
#
file(COPY "${Boost_LIBRARY_DIRS}/" DESTINATION "${CMAKE_BINARY_DIR}/bin")
file(COPY "${py_dll_path}" DESTINATION "${CMAKE_BINARY_DIR}/bin")
```
貢獻指南
這個儲存庫沒有索引到貢獻指南
研究方向
在列出的 Python 2.7 和 3.6 設定下,使用附帶的 CMakeLists.txt 建置提供的 main.cpp,然後比較列印出的除法結果。閱讀相關的 examples/ 程式碼,並使用重現的輸出來判斷 Python 3 的行為是否符合預期,以及是否存在受支援的非向下取整除法路徑;完成的標準是取得 maintainer 確認的解釋,或精確識別出的 fix。
由索引模型根據 Issue 內容生成。
評估
- 技術堆疊
- cpp, python
- 領域
- backend
- Issue 類型
- 缺陷
- 難度
- 4/5
- 預估耗時
- 3-5 天
- 活躍度
- 停滯
- 描述清晰度
- 需要釐清
- 新手友好度
- 25/100