Skip to content

Commit 0b3df7f

Browse files
ax3lhenryiii
andauthored
ci: Intel icc/icpc via oneAPI (#2573)
* CI: Intel icc/icpc via oneAPI Add testing for Intel icc/icpc via the oneAPI images. Intel oneAPI is in a late beta stage, currently shipping oneAPI beta09 with ICC 20.2. * CI: Skip Interpreter Tests for Intel Cannot find how to add this, neiter the package `libc6-dev` nor `intel-oneapi-mkl-devel` help when installed to solve this: ``` -- Looking for C++ include pthread.h -- Looking for C++ include pthread.h - not found CMake Error at /__t/cmake/3.18.4/x64/cmake-3.18.4-Linux-x86_64/share/cmake-3.18/Modules/FindPackageHandleStandardArgs.cmake:165 (message): Could NOT find Threads (missing: Threads_FOUND) Call Stack (most recent call first): /__t/cmake/3.18.4/x64/cmake-3.18.4-Linux-x86_64/share/cmake-3.18/Modules/FindPackageHandleStandardArgs.cmake:458 (_FPHSA_FAILURE_MESSAGE) /__t/cmake/3.18.4/x64/cmake-3.18.4-Linux-x86_64/share/cmake-3.18/Modules/FindThreads.cmake:234 (FIND_PACKAGE_HANDLE_STANDARD_ARGS) tests/test_embed/CMakeLists.txt:17 (find_package) ``` * CI: libc6-dev from GCC for ICC * CI: Run bare metal for oneAPI * CI: Ubuntu 18.04 for oneAPI * CI: Intel +Catch -Eigen * CI: CMake from Apt (ICC tests) * CI: Replace Intel Py with GCC Py * CI: Intel w/o GCC's Eigen * CI: ICC with verbose make * [Debug] Find core dump * tests: use arg{} instead of arg() for Intel * tests: adding a few more missing {} * fix: sync with @tobiasleibner's branch * fix: try ubuntu 20-04 * fix: drop exit 1 * style: clang tidy fix * style: fix missing NOLINT * ICC: Update Compiler Name Changed upstream with the last oneAPI release. * ICC CI: Downgrade pytest pytest 6 does not capture the `discard_as_unraisable` stderr and just writes a warning with its content instead. * Use new test pinning requirements.txt * tests: add notes about intel, cleanup Co-authored-by: Henry Schreiner <[email protected]>
1 parent 0f8d5f2 commit 0b3df7f

8 files changed

+115
-31
lines changed

.github/workflows/ci.yml

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,7 @@ jobs:
412412
- name: Interface test
413413
run: cmake3 --build build --target test_cmake_build
414414

415+
415416
# Testing on GCC using the GCC docker images (only recent images supported)
416417
gcc:
417418
runs-on: ubuntu-latest
@@ -464,6 +465,78 @@ jobs:
464465
run: cmake --build build --target test_cmake_build
465466

466467

468+
# Testing on ICC using the oneAPI apt repo
469+
icc:
470+
runs-on: ubuntu-20.04
471+
strategy:
472+
fail-fast: false
473+
474+
name: "🐍 3 • ICC latest • x64"
475+
476+
steps:
477+
- uses: actions/checkout@v1
478+
479+
- name: Add apt repo
480+
run: |
481+
sudo apt-get update
482+
sudo apt-get install -y wget build-essential pkg-config cmake ca-certificates gnupg
483+
wget https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS-2023.PUB
484+
sudo apt-key add GPG-PUB-KEY-INTEL-SW-PRODUCTS-2023.PUB
485+
echo "deb https://apt.repos.intel.com/oneapi all main" | sudo tee /etc/apt/sources.list.d/oneAPI.list
486+
487+
- name: Add ICC & Python 3
488+
run: sudo apt-get update; sudo apt-get install -y intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic cmake python3-dev python3-numpy python3-pytest python3-pip
489+
490+
- name: Update pip
491+
shell: bash
492+
run: |
493+
set +e; source /opt/intel/oneapi/setvars.sh; set -e
494+
python3 -m pip install --upgrade pip
495+
496+
- name: Install dependencies
497+
run: |
498+
set +e; source /opt/intel/oneapi/setvars.sh; set -e
499+
python3 -m pip install -r tests/requirements.txt --prefer-binary
500+
501+
- name: Configure
502+
shell: bash
503+
run: |
504+
set +e; source /opt/intel/oneapi/setvars.sh; set -e
505+
cmake -S . -B build \
506+
-DPYBIND11_WERROR=ON \
507+
-DDOWNLOAD_CATCH=ON \
508+
-DDOWNLOAD_EIGEN=OFF \
509+
-DCMAKE_CXX_STANDARD=11 \
510+
-DCMAKE_CXX_COMPILER=$(which icpc) \
511+
-DCMAKE_VERBOSE_MAKEFILE=ON \
512+
-DPYTHON_EXECUTABLE=$(python3 -c "import sys; print(sys.executable)")
513+
514+
- name: Build
515+
shell: bash
516+
run: |
517+
set +e; source /opt/intel/oneapi/setvars.sh; set -e
518+
cmake --build build -j 2
519+
520+
- name: Python tests
521+
shell: bash
522+
run: |
523+
set +e; source /opt/intel/oneapi/setvars.sh; set -e
524+
sudo service apport stop
525+
cmake --build build --target check
526+
527+
- name: C++ tests
528+
shell: bash
529+
run: |
530+
set +e; source /opt/intel/oneapi/setvars.sh; set -e
531+
cmake --build build --target cpptest
532+
533+
- name: Interface test
534+
shell: bash
535+
run: |
536+
set +e; source /opt/intel/oneapi/setvars.sh; set -e
537+
cmake --build build --target test_cmake_build
538+
539+
467540
# Testing on CentOS (manylinux uses a centos base, and this is an easy way
468541
# to get GCC 4.8, which is the manylinux1 compiler).
469542
centos:

tests/test_builtin_casters.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,9 +183,11 @@ TEST_SUBMODULE(builtin_casters, m) {
183183
m.def("load_nullptr_t", [](std::nullptr_t) {}); // not useful, but it should still compile
184184
m.def("cast_nullptr_t", []() { return std::nullptr_t{}; });
185185

186+
// [workaround(intel)] ICC 20/21 breaks with py::arg().stuff, using py::arg{}.stuff works.
187+
186188
// test_bool_caster
187189
m.def("bool_passthrough", [](bool arg) { return arg; });
188-
m.def("bool_passthrough_noconvert", [](bool arg) { return arg; }, py::arg().noconvert());
190+
m.def("bool_passthrough_noconvert", [](bool arg) { return arg; }, py::arg{}.noconvert());
189191

190192
// test_reference_wrapper
191193
m.def("refwrap_builtin", [](std::reference_wrapper<int> p) { return 10 * p.get(); });

tests/test_callbacks.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,8 @@ TEST_SUBMODULE(callbacks, m) {
119119

120120
class AbstractBase {
121121
public:
122-
virtual ~AbstractBase() = default;
122+
// [workaround(intel)] = default does not work here
123+
virtual ~AbstractBase() {}; // NOLINT(modernize-use-equals-default)
123124
virtual unsigned int func() = 0;
124125
};
125126
m.def("func_accepting_func_accepting_base", [](std::function<double(AbstractBase&)>) { });

tests/test_class.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,8 @@ TEST_SUBMODULE(class_, m) {
323323

324324
class PublicistB : public ProtectedB {
325325
public:
326+
// [workaround(intel)] = default does not work here
327+
~PublicistB() override {}; // NOLINT(modernize-use-equals-default)
326328
using ProtectedB::foo;
327329
};
328330

tests/test_custom_type_casters.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -99,19 +99,20 @@ TEST_SUBMODULE(custom_type_casters, m) {
9999
}
100100
static ArgInspector2 h(ArgInspector2 a, ArgAlwaysConverts) { return a; }
101101
};
102+
// [workaround(intel)] ICC 20/21 breaks with py::arg().stuff, using py::arg{}.stuff works.
102103
py::class_<ArgInspector>(m, "ArgInspector")
103104
.def(py::init<>())
104105
.def("f", &ArgInspector::f, py::arg(), py::arg() = ArgAlwaysConverts())
105106
.def("g", &ArgInspector::g, "a"_a.noconvert(), "b"_a, "c"_a.noconvert()=13, "d"_a=ArgInspector2(), py::arg() = ArgAlwaysConverts())
106-
.def_static("h", &ArgInspector::h, py::arg().noconvert(), py::arg() = ArgAlwaysConverts())
107+
.def_static("h", &ArgInspector::h, py::arg{}.noconvert(), py::arg() = ArgAlwaysConverts())
107108
;
108109
m.def("arg_inspect_func", [](ArgInspector2 a, ArgInspector1 b, ArgAlwaysConverts) { return a.arg + "\n" + b.arg; },
109-
py::arg().noconvert(false), py::arg_v(nullptr, ArgInspector1()).noconvert(true), py::arg() = ArgAlwaysConverts());
110+
py::arg{}.noconvert(false), py::arg_v(nullptr, ArgInspector1()).noconvert(true), py::arg() = ArgAlwaysConverts());
110111

111-
m.def("floats_preferred", [](double f) { return 0.5 * f; }, py::arg("f"));
112-
m.def("floats_only", [](double f) { return 0.5 * f; }, py::arg("f").noconvert());
113-
m.def("ints_preferred", [](int i) { return i / 2; }, py::arg("i"));
114-
m.def("ints_only", [](int i) { return i / 2; }, py::arg("i").noconvert());
112+
m.def("floats_preferred", [](double f) { return 0.5 * f; }, "f"_a);
113+
m.def("floats_only", [](double f) { return 0.5 * f; }, "f"_a.noconvert());
114+
m.def("ints_preferred", [](int i) { return i / 2; }, "i"_a);
115+
m.def("ints_only", [](int i) { return i / 2; }, "i"_a.noconvert());
115116

116117
// test_custom_caster_destruction
117118
// Test that `take_ownership` works on types with a custom type caster when given a pointer

tests/test_eigen.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -273,24 +273,25 @@ TEST_SUBMODULE(eigen, m) {
273273
m.def("cpp_ref_r", [](py::handle m) { return m.cast<Eigen::Ref<MatrixXdR>>()(1, 0); });
274274
m.def("cpp_ref_any", [](py::handle m) { return m.cast<py::EigenDRef<Eigen::MatrixXd>>()(1, 0); });
275275

276+
// [workaround(intel)] ICC 20/21 breaks with py::arg().stuff, using py::arg{}.stuff works.
276277

277278
// test_nocopy_wrapper
278279
// Test that we can prevent copying into an argument that would normally copy: First a version
279280
// that would allow copying (if types or strides don't match) for comparison:
280281
m.def("get_elem", &get_elem);
281282
// Now this alternative that calls the tells pybind to fail rather than copy:
282283
m.def("get_elem_nocopy", [](Eigen::Ref<const Eigen::MatrixXd> m) -> double { return get_elem(m); },
283-
py::arg().noconvert());
284+
py::arg{}.noconvert());
284285
// Also test a row-major-only no-copy const ref:
285286
m.def("get_elem_rm_nocopy", [](Eigen::Ref<const Eigen::Matrix<long, -1, -1, Eigen::RowMajor>> &m) -> long { return m(2, 1); },
286-
py::arg().noconvert());
287+
py::arg{}.noconvert());
287288

288289
// test_issue738
289290
// Issue #738: 1xN or Nx1 2D matrices were neither accepted nor properly copied with an
290291
// incompatible stride value on the length-1 dimension--but that should be allowed (without
291292
// requiring a copy!) because the stride value can be safely ignored on a size-1 dimension.
292-
m.def("iss738_f1", &adjust_matrix<const Eigen::Ref<const Eigen::MatrixXd> &>, py::arg().noconvert());
293-
m.def("iss738_f2", &adjust_matrix<const Eigen::Ref<const Eigen::Matrix<double, -1, -1, Eigen::RowMajor>> &>, py::arg().noconvert());
293+
m.def("iss738_f1", &adjust_matrix<const Eigen::Ref<const Eigen::MatrixXd> &>, py::arg{}.noconvert());
294+
m.def("iss738_f2", &adjust_matrix<const Eigen::Ref<const Eigen::Matrix<double, -1, -1, Eigen::RowMajor>> &>, py::arg{}.noconvert());
294295

295296
// test_issue1105
296297
// Issue #1105: when converting from a numpy two-dimensional (Nx1) or (1xN) value into a dense

tests/test_methods_and_attributes.cpp

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -322,22 +322,24 @@ TEST_SUBMODULE(methods_and_attributes, m) {
322322
m.def("should_fail", [](int, UnregisteredType) {}, py::arg(), py::arg() = UnregisteredType());
323323
});
324324

325+
// [workaround(intel)] ICC 20/21 breaks with py::arg().stuff, using py::arg{}.stuff works.
326+
325327
// test_accepts_none
326328
py::class_<NoneTester, std::shared_ptr<NoneTester>>(m, "NoneTester")
327329
.def(py::init<>());
328-
m.def("no_none1", &none1, py::arg().none(false));
329-
m.def("no_none2", &none2, py::arg().none(false));
330-
m.def("no_none3", &none3, py::arg().none(false));
331-
m.def("no_none4", &none4, py::arg().none(false));
332-
m.def("no_none5", &none5, py::arg().none(false));
330+
m.def("no_none1", &none1, py::arg{}.none(false));
331+
m.def("no_none2", &none2, py::arg{}.none(false));
332+
m.def("no_none3", &none3, py::arg{}.none(false));
333+
m.def("no_none4", &none4, py::arg{}.none(false));
334+
m.def("no_none5", &none5, py::arg{}.none(false));
333335
m.def("ok_none1", &none1);
334-
m.def("ok_none2", &none2, py::arg().none(true));
336+
m.def("ok_none2", &none2, py::arg{}.none(true));
335337
m.def("ok_none3", &none3);
336-
m.def("ok_none4", &none4, py::arg().none(true));
338+
m.def("ok_none4", &none4, py::arg{}.none(true));
337339
m.def("ok_none5", &none5);
338340

339-
m.def("no_none_kwarg", &none2, py::arg("a").none(false));
340-
m.def("no_none_kwarg_kw_only", &none2, py::kw_only(), py::arg("a").none(false));
341+
m.def("no_none_kwarg", &none2, "a"_a.none(false));
342+
m.def("no_none_kwarg_kw_only", &none2, py::kw_only(), "a"_a.none(false));
341343

342344
// test_str_issue
343345
// Issue #283: __str__ called on uninitialized instance when constructor arguments invalid

tests/test_numpy_array.cpp

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -258,9 +258,11 @@ TEST_SUBMODULE(numpy_array, sm) {
258258
sm.def("overloaded2", [](py::array_t<std::complex<float>>) { return "float complex"; });
259259
sm.def("overloaded2", [](py::array_t<float>) { return "float"; });
260260

261+
// [workaround(intel)] ICC 20/21 breaks with py::arg().stuff, using py::arg{}.stuff works.
262+
261263
// Only accept the exact types:
262-
sm.def("overloaded3", [](py::array_t<int>) { return "int"; }, py::arg().noconvert());
263-
sm.def("overloaded3", [](py::array_t<double>) { return "double"; }, py::arg().noconvert());
264+
sm.def("overloaded3", [](py::array_t<int>) { return "int"; }, py::arg{}.noconvert());
265+
sm.def("overloaded3", [](py::array_t<double>) { return "double"; }, py::arg{}.noconvert());
264266

265267
// Make sure we don't do unsafe coercion (e.g. float to int) when not using forcecast, but
266268
// rather that float gets converted via the safe (conversion to double) overload:
@@ -284,7 +286,7 @@ TEST_SUBMODULE(numpy_array, sm) {
284286
for (py::ssize_t i = 0; i < r.shape(0); i++)
285287
for (py::ssize_t j = 0; j < r.shape(1); j++)
286288
r(i, j) += v;
287-
}, py::arg().noconvert(), py::arg());
289+
}, py::arg{}.noconvert(), py::arg());
288290

289291
sm.def("proxy_init3", [](double start) {
290292
py::array_t<double, py::array::c_style> a({ 3, 3, 3 });
@@ -338,7 +340,7 @@ TEST_SUBMODULE(numpy_array, sm) {
338340
for (py::ssize_t i = 0; i < r.shape(0); i++)
339341
for (py::ssize_t j = 0; j < r.shape(1); j++)
340342
r(i, j) += v;
341-
}, py::arg().noconvert(), py::arg());
343+
}, py::arg{}.noconvert(), py::arg());
342344
sm.def("proxy_init3_dyn", [](double start) {
343345
py::array_t<double, py::array::c_style> a({ 3, 3, 3 });
344346
auto r = a.mutable_unchecked();
@@ -419,20 +421,20 @@ TEST_SUBMODULE(numpy_array, sm) {
419421
py::arg("a"));
420422
sm.def("accept_double_noconvert",
421423
[](py::array_t<double, 0>) {},
422-
py::arg("a").noconvert());
424+
"a"_a.noconvert());
423425
sm.def("accept_double_forcecast_noconvert",
424426
[](py::array_t<double, py::array::forcecast>) {},
425-
py::arg("a").noconvert());
427+
"a"_a.noconvert());
426428
sm.def("accept_double_c_style_noconvert",
427429
[](py::array_t<double, py::array::c_style>) {},
428-
py::arg("a").noconvert());
430+
"a"_a.noconvert());
429431
sm.def("accept_double_c_style_forcecast_noconvert",
430432
[](py::array_t<double, py::array::forcecast | py::array::c_style>) {},
431-
py::arg("a").noconvert());
433+
"a"_a.noconvert());
432434
sm.def("accept_double_f_style_noconvert",
433435
[](py::array_t<double, py::array::f_style>) {},
434-
py::arg("a").noconvert());
436+
"a"_a.noconvert());
435437
sm.def("accept_double_f_style_forcecast_noconvert",
436438
[](py::array_t<double, py::array::forcecast | py::array::f_style>) {},
437-
py::arg("a").noconvert());
439+
"a"_a.noconvert());
438440
}

0 commit comments

Comments
 (0)