From 4e7aba5842f0ff2abfd5b43fda2a226b49c5c72f Mon Sep 17 00:00:00 2001 From: Casper da Costa-Luis Date: Sun, 3 Oct 2021 18:14:31 +0100 Subject: [PATCH 1/9] faster startup replace `pkg_resources` => `importlib.resources` --- cuvec/__init__.py | 13 ++++++++----- setup.cfg | 4 +++- tests/test_cuvec.py | 14 ++++++++++++++ 3 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 tests/test_cuvec.py diff --git a/cuvec/__init__.py b/cuvec/__init__.py index 998781f..29d561e 100644 --- a/cuvec/__init__.py +++ b/cuvec/__init__.py @@ -25,9 +25,10 @@ # data 'typecodes', 'vec_types'] # yapf: disable -from pathlib import Path - -from pkg_resources import resource_filename +try: # py<3.9 + import importlib_resources as resources +except ImportError: + from importlib import resources try: from .cuvec import dev_sync @@ -37,6 +38,8 @@ else: from .pycuvec import CuVec, asarray, copy, cu_copy, cu_zeros, typecodes, vec_types, zeros +p = resources.files('cuvec').resolve() +# for C++/CUDA/SWIG includes +include_path = p / 'include' # for use in `cmake -DCMAKE_PREFIX_PATH=...` -cmake_prefix = Path(resource_filename(__name__, "cmake")).resolve() -include_path = Path(resource_filename(__name__, "include")).resolve() +cmake_prefix = p / 'cmake' diff --git a/setup.cfg b/setup.cfg index f20f32b..d4e0a58 100644 --- a/setup.cfg +++ b/setup.cfg @@ -42,7 +42,9 @@ setup_requires= scikit-build>=0.11.0 cmake>=3.18 ninja -install_requires=setuptools; numpy +install_requires= + importlib_resources; python_version < "3.9" + numpy python_requires=>=3.6 [options.extras_require] dev= diff --git a/tests/test_cuvec.py b/tests/test_cuvec.py new file mode 100644 index 0000000..f036c48 --- /dev/null +++ b/tests/test_cuvec.py @@ -0,0 +1,14 @@ +import cuvec as cu + + +def test_includes(): + assert cu.include_path.is_dir() + assert {i.name for i in cu.include_path.iterdir()} == {'cuvec.cuh', 'pycuvec.cuh', 'cuvec.i'} + + +def test_cmake_prefix(): + assert cu.cmake_prefix.is_dir() + assert {i.name + for i in cu.cmake_prefix.iterdir()} == { + f'AMYPADcuvec{i}.cmake' + for i in ('Config', 'ConfigVersion', 'Targets', 'Targets-release')} From 96bad7491c47d54affa7ab0e877bd656b0657857 Mon Sep 17 00:00:00 2001 From: Casper da Costa-Luis Date: Mon, 1 Nov 2021 13:42:07 +0000 Subject: [PATCH 2/9] add `asPyCuVec` convenience --- cuvec/include/pycuvec.cuh | 19 +++++++++++++++++++ cuvec/src/example_mod/example_mod.cu | 4 +++- docs/index.md | 10 +++++++--- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/cuvec/include/pycuvec.cuh b/cuvec/include/pycuvec.cuh index e02cc6e..2eb5d35 100644 --- a/cuvec/include/pycuvec.cuh +++ b/cuvec/include/pycuvec.cuh @@ -229,5 +229,24 @@ template PyCuVec *PyCuVec_deepcopy(PyCuVec *other) { self->strides = other->strides; return self; } +/// returns `getattr(o, 'cuvec', o) or NULL` without altering refcount +template PyCuVec *asPyCuVec(PyObject *o) { + if (!o || Py_None == o) return NULL; + if (PyObject_HasAttrString(o, "cuvec")) { + o = PyObject_GetAttrString(o, "cuvec"); + if (!o) return NULL; + Py_DECREF(o); + } + return (PyCuVec *)o; +} +template PyCuVec *asPyCuVec(PyCuVec *o) { + if (!o || Py_None == (PyObject *)o) return NULL; + if (PyObject_HasAttrString((PyObject *)o, "cuvec")) { + o = (PyCuVec *)PyObject_GetAttrString((PyObject *)o, "cuvec"); + if (!o) return NULL; + Py_DECREF((PyObject *)o); + } + return o; +} #endif // _PYCUVEC_H_ diff --git a/cuvec/src/example_mod/example_mod.cu b/cuvec/src/example_mod/example_mod.cu index 941ceb2..4a610f5 100644 --- a/cuvec/src/example_mod/example_mod.cu +++ b/cuvec/src/example_mod/example_mod.cu @@ -19,12 +19,14 @@ __global__ void _d_incr(float *dst, float *src, int X, int Y) { } #endif // CUVEC_DISABLE_CUDA static PyObject *increment2d_f(PyObject *self, PyObject *args, PyObject *kwargs) { - PyCuVec *dst = NULL; PyCuVec *src = NULL; + PyCuVec *dst = NULL; static const char *kwds[] = {"src", "output", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", (char **)kwds, (PyObject **)&src, (PyObject **)&dst)) return NULL; + src = asPyCuVec(src); + dst = asPyCuVec(dst); if (!src) return NULL; std::vector &N = src->shape; if (N.size() != 2) { diff --git a/docs/index.md b/docs/index.md index d681b1a..13fd7eb 100644 --- a/docs/index.md +++ b/docs/index.md @@ -72,6 +72,10 @@ Requirements: // PyCuVec *PyCuVec_zeros(std::vector shape); // PyCuVec *PyCuVec_zeros_like(PyCuVec *other); // PyCuVec *PyCuVec_deepcopy(PyCuVec *other); + /// returns `NULL` if `self is None`, or + /// `getattr(self, 'cuvec', self)` otherwise + // PyCuVec *asPyCuVec(PyObject *self); + // PyCuVec *asPyCuVec(PyCuVec *self); ``` === "C++/SWIG API" @@ -165,7 +169,7 @@ Python: import cuvec, numpy, mymod arr = cuvec.zeros((1337, 42, 7), "float32") assert all(numpy.mean(arr, axis=(0, 1)) == 0) - print(cuvec.asarray(mymod.myfunc(arr.cuvec)).sum()) + print(cuvec.asarray(mymod.myfunc(arr)).sum()) ``` === "Alternative: with CuVec & SWIG" @@ -236,8 +240,8 @@ C++: if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", (char **)kwds, (PyObject **)&src, (PyObject **)&dst)) return NULL; - - + src = asPyCuVec(src); + dst = asPyCuVec(dst); if (!src) return NULL; From 38c10b83f12212ed8b4993eab501eae5708e7c4b Mon Sep 17 00:00:00 2001 From: Casper da Costa-Luis Date: Mon, 1 Nov 2021 13:54:34 +0000 Subject: [PATCH 3/9] test example_mod --- cuvec/src/example_mod/example_mod.cu | 14 ++++++++++---- tests/test_perf.py | 21 +++++++-------------- tests/test_pycuvec.py | 15 +++++++++++++++ 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/cuvec/src/example_mod/example_mod.cu b/cuvec/src/example_mod/example_mod.cu index 4a610f5..0a25413 100644 --- a/cuvec/src/example_mod/example_mod.cu +++ b/cuvec/src/example_mod/example_mod.cu @@ -21,9 +21,10 @@ __global__ void _d_incr(float *dst, float *src, int X, int Y) { static PyObject *increment2d_f(PyObject *self, PyObject *args, PyObject *kwargs) { PyCuVec *src = NULL; PyCuVec *dst = NULL; - static const char *kwds[] = {"src", "output", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", (char **)kwds, (PyObject **)&src, - (PyObject **)&dst)) + bool timing = false; + static const char *kwds[] = {"src", "output", "timing", NULL}; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Ob", (char **)kwds, (PyObject **)&src, + (PyObject **)&dst, &timing)) return NULL; src = asPyCuVec(src); dst = asPyCuVec(dst); @@ -74,7 +75,12 @@ static PyObject *increment2d_f(PyObject *self, PyObject *args, PyObject *kwargs) double kernel_ms = std::chrono::duration(eKern - eAlloc).count(); // fprintf(stderr, "%.3lf ms, %.3lf ms\n", alloc_ms, kernel_ms); #endif - return Py_BuildValue("ddN", double(alloc_ms), double(kernel_ms), (PyObject *)dst); + if (timing) { + // hack: store times in first two elements of output + dst->vec[0] = alloc_ms; + dst->vec[1] = kernel_ms; + } + return (PyObject *)dst; } static PyMethodDef example_methods[] = { {"increment2d_f", (PyCFunction)increment2d_f, METH_VARARGS | METH_KEYWORDS, diff --git a/tests/test_perf.py b/tests/test_perf.py index 9df3333..dc02f84 100644 --- a/tests/test_perf.py +++ b/tests/test_perf.py @@ -67,24 +67,17 @@ def test_perf(cu, ex, shape=(1337, 42), quiet=False): t['assign'] = (time() - tic - overhead) * 1000 if not quiet: - if cu is sw: - t['warmup'], res = timer(ex.increment2d_f)(src.cuvec, None, True) - t['> create dst'], t['> kernel'] = cu.asarray(res)[0, :2] - else: - t['warmup'], (t['> create dst'], t['> kernel'], _) = timer(ex.increment2d_f)(src.cuvec) - if cu is sw: - t['call ext'], res = timer(ex.increment2d_f)(src.cuvec, None, True) - t['- create dst'], t['- kernel'] = None, None - t['view'], dst = timer(cu.asarray)(res) - t['- create dst'], t['- kernel'] = dst[0, :2] - else: - t['call ext'], (t['- create dst'], t['- kernel'], res) = timer(ex.increment2d_f)(src.cuvec) - t['view'], dst = timer(cu.asarray)(res) + t['warmup'], res = timer(ex.increment2d_f)(src.cuvec, None, True) + t['> create dst'], t['> kernel'] = cu.asarray(res)[0, :2] + t['call ext'], res = timer(ex.increment2d_f)(src.cuvec, None, True) + t['- create dst'], t['- kernel'] = None, None + t['view'], dst = timer(cu.asarray)(res) + t['- create dst'], t['- kernel'] = dst[0, :2] if not quiet: print("\n".join(f"{k.ljust(14)} | {v:.3f}" for k, v in t.items())) assert (src + 1 == dst)[1:].all() - assert (src + 1 == dst)[0, 2 if cu is sw else 0:].all() + assert (src + 1 == dst)[0, 2:].all() # even a fast kernel takes longer than API overhead assert t['- kernel'] / (t['call ext'] - t['- create dst']) > 0.5 # API call should be <0.1 ms... but set a higher threshold of 2 ms diff --git a/tests/test_pycuvec.py b/tests/test_pycuvec.py index 518e985..9e48e90 100644 --- a/tests/test_pycuvec.py +++ b/tests/test_pycuvec.py @@ -123,3 +123,18 @@ def test_cuda_array_interface(): assert ndarr.dtype == v.dtype with raises(AttributeError): ndarr.__cuda_array_interface__ + + +def test_increment(): + # `example_mod` is defined in ../cuvec/src/example_mod/ + from cuvec.example_mod import increment2d_f + a = cu.zeros((1337, 42), 'f') + assert (a == 0).all() + increment2d_f(a.cuvec, a.cuvec) + assert (a == 1).all() + + a[:] = 0 + assert (a == 0).all() + + res = cu.asarray(increment2d_f(a)) + assert (res == 1).all() From 0a9d190da070434f7572702fb319a374447829cb Mon Sep 17 00:00:00 2001 From: Casper da Costa-Luis Date: Mon, 1 Nov 2021 13:59:20 +0000 Subject: [PATCH 4/9] minor test updates --- tests/test_pycuvec.py | 4 +++- tests/test_swigcuvec.py | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/test_pycuvec.py b/tests/test_pycuvec.py index 9e48e90..e89fff5 100644 --- a/tests/test_pycuvec.py +++ b/tests/test_pycuvec.py @@ -130,11 +130,13 @@ def test_increment(): from cuvec.example_mod import increment2d_f a = cu.zeros((1337, 42), 'f') assert (a == 0).all() - increment2d_f(a.cuvec, a.cuvec) + res = cu.asarray(increment2d_f(a.cuvec, a.cuvec)) assert (a == 1).all() + assert (res == 1).all() a[:] = 0 assert (a == 0).all() + assert (res == 0).all() res = cu.asarray(increment2d_f(a)) assert (res == 1).all() diff --git a/tests/test_swigcuvec.py b/tests/test_swigcuvec.py index 83962ab..d81ef61 100644 --- a/tests/test_swigcuvec.py +++ b/tests/test_swigcuvec.py @@ -145,11 +145,13 @@ def test_increment(): from cuvec.example_swig import increment2d_f a = cu.zeros((1337, 42), 'f') assert (a == 0).all() - increment2d_f(a.cuvec, a.cuvec) + res = cu.asarray(increment2d_f(a.cuvec, a.cuvec)) assert (a == 1).all() + assert (res == 1).all() a[:] = 0 assert (a == 0).all() + assert (res == 0).all() res = cu.asarray(increment2d_f(a.cuvec)) assert (res == 1).all() From e0fa33bb1071e7c10c1c5c3ce8ebb88173ac7874 Mon Sep 17 00:00:00 2001 From: Casper da Costa-Luis Date: Mon, 1 Nov 2021 15:22:08 +0000 Subject: [PATCH 5/9] fix & document SWIG --- cuvec/swigcuvec.py | 19 +++++++++++++++++-- tests/test_swigcuvec.py | 4 +--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/cuvec/swigcuvec.py b/cuvec/swigcuvec.py index afc6579..79f1063 100644 --- a/cuvec/swigcuvec.py +++ b/cuvec/swigcuvec.py @@ -172,13 +172,28 @@ def copy(arr) -> CuVec: return CuVec(cu_copy(arr)) -def asarray(arr, dtype=None, order=None) -> CuVec: +def asarray(arr, dtype=None, order=None, ownership: str = 'warning') -> CuVec: """ Returns a `swigcuvec.CuVec` view of `arr`, avoiding memory copies if possible. (`cuvec` equivalent of `numpy.asarray`). + + Args: + ownership: logging level if `is_raw_cuvec(arr)`. + WARNING: `asarray()` should not be used on an existing reference, e.g.: + >>> res = asarray(some_swig_api_func(..., output=getattr(out, 'cuvec', None))) + `res.cuvec` and `out.cuvec` are now the same + yet garbage collected separately (dangling ptr). + Instead, use: + >>> res = some_swig_api_func(..., output=getattr(out, 'cuvec', None)) + >>> res = out if hasattr(out, 'cuvec') else asarray(res) + NB: `asarray()` is safe if the raw cuvec was created in C++/SWIG, e.g.: + >>> res = asarray(some_swig_api_func(..., output=None), ownership='debug') """ if is_raw_cuvec(arr): - log.debug("taking ownership") + ownership = ownership.lower() + if ownership in {'critical', 'fatal', 'error'}: + raise IOError("Can't take ownership of existing cuvec (would create dangling ptr)") + getattr(log, ownership)("taking ownership") arr = SWIGVector(None, None, arr) if not isinstance(arr, np.ndarray) and is_raw_swvec(arr): res = CuVec(arr) diff --git a/tests/test_swigcuvec.py b/tests/test_swigcuvec.py index d81ef61..83962ab 100644 --- a/tests/test_swigcuvec.py +++ b/tests/test_swigcuvec.py @@ -145,13 +145,11 @@ def test_increment(): from cuvec.example_swig import increment2d_f a = cu.zeros((1337, 42), 'f') assert (a == 0).all() - res = cu.asarray(increment2d_f(a.cuvec, a.cuvec)) + increment2d_f(a.cuvec, a.cuvec) assert (a == 1).all() - assert (res == 1).all() a[:] = 0 assert (a == 0).all() - assert (res == 0).all() res = cu.asarray(increment2d_f(a.cuvec)) assert (res == 1).all() From 7c38b15b40d82f51ce26c01324bb2d65fa17eac6 Mon Sep 17 00:00:00 2001 From: Casper da Costa-Luis Date: Mon, 1 Nov 2021 18:52:06 +0000 Subject: [PATCH 6/9] add tests for SWIG ownership --- tests/test_swigcuvec.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test_swigcuvec.py b/tests/test_swigcuvec.py index 83962ab..a05d1f2 100644 --- a/tests/test_swigcuvec.py +++ b/tests/test_swigcuvec.py @@ -109,6 +109,8 @@ def test_asarray(): assert (s == v[1:]).all() assert str(s.swvec) != str(v.swvec) assert np.asarray(s.swvec).data != np.asarray(v.swvec).data + with raises(IOError): + cu.asarray(s.swvec.cuvec, ownership='error') def test_cuda_array_interface(): From 32be18f4dd01e216b3f2549277afa352162159ec Mon Sep 17 00:00:00 2001 From: Casper da Costa-Luis Date: Mon, 1 Nov 2021 15:27:24 +0000 Subject: [PATCH 7/9] fix example_mod danglilng ptr --- cuvec/src/example_mod/example_mod.cu | 1 + tests/test_pycuvec.py | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/cuvec/src/example_mod/example_mod.cu b/cuvec/src/example_mod/example_mod.cu index 0a25413..3b6d7d5 100644 --- a/cuvec/src/example_mod/example_mod.cu +++ b/cuvec/src/example_mod/example_mod.cu @@ -50,6 +50,7 @@ static PyObject *increment2d_f(PyObject *self, PyObject *args, PyObject *kwargs) PyErr_SetString(PyExc_IndexError, "`output` must be same shape as `src`"); return NULL; } + Py_INCREF((PyObject *)dst); // anticipating returning } else { dst = PyCuVec_zeros_like(src); if (!dst) return NULL; diff --git a/tests/test_pycuvec.py b/tests/test_pycuvec.py index e89fff5..2eaa26e 100644 --- a/tests/test_pycuvec.py +++ b/tests/test_pycuvec.py @@ -140,3 +140,13 @@ def test_increment(): res = cu.asarray(increment2d_f(a)) assert (res == 1).all() + + +def test_increment_return(): + from cuvec.example_mod import increment2d_f + a = cu.zeros((1337, 42), 'f') + assert (a == 0).all() + res = cu.asarray(increment2d_f(a, a)) + assert (a == 1).all() + del a + assert (res == 1).all() From e833075dc2e5e4e3c03b0d49dfe741d213cd2cdc Mon Sep 17 00:00:00 2001 From: Casper da Costa-Luis Date: Mon, 1 Nov 2021 18:12:21 +0000 Subject: [PATCH 8/9] add asPyCuVec_T converter functions --- cuvec/include/pycuvec.cuh | 20 ++++++++++++++++++++ cuvec/src/example_mod/example_mod.cu | 5 ++--- docs/index.md | 26 ++++++++++++++++++++------ 3 files changed, 42 insertions(+), 9 deletions(-) diff --git a/cuvec/include/pycuvec.cuh b/cuvec/include/pycuvec.cuh index 2eb5d35..ecaf8eb 100644 --- a/cuvec/include/pycuvec.cuh +++ b/cuvec/include/pycuvec.cuh @@ -248,5 +248,25 @@ template PyCuVec *asPyCuVec(PyCuVec *o) { } return o; } +/// conversion functions for PyArg_Parse...(..., "O&", ...) +#define ASCUVEC(T, typechar) \ + int asPyCuVec_##typechar(PyObject *object, void **address) { \ + *address = (void *)asPyCuVec(object); \ + return 1; \ + } +ASCUVEC(signed char, b) +ASCUVEC(unsigned char, B) +ASCUVEC(char, c) +ASCUVEC(short, h) +ASCUVEC(unsigned short, H) +ASCUVEC(int, i) +ASCUVEC(unsigned int, I) +ASCUVEC(long long, q) +ASCUVEC(unsigned long long, Q) +#ifdef _CUVEC_HALF +ASCUVEC(_CUVEC_HALF, e) +#endif +ASCUVEC(float, f) +ASCUVEC(double, d) #endif // _PYCUVEC_H_ diff --git a/cuvec/src/example_mod/example_mod.cu b/cuvec/src/example_mod/example_mod.cu index 3b6d7d5..ba81694 100644 --- a/cuvec/src/example_mod/example_mod.cu +++ b/cuvec/src/example_mod/example_mod.cu @@ -23,10 +23,9 @@ static PyObject *increment2d_f(PyObject *self, PyObject *args, PyObject *kwargs) PyCuVec *dst = NULL; bool timing = false; static const char *kwds[] = {"src", "output", "timing", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Ob", (char **)kwds, (PyObject **)&src, - (PyObject **)&dst, &timing)) + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|Ob", (char **)kwds, &asPyCuVec_f, &src, &dst, + &timing)) return NULL; - src = asPyCuVec(src); dst = asPyCuVec(dst); if (!src) return NULL; std::vector &N = src->shape; diff --git a/docs/index.md b/docs/index.md index 13fd7eb..80d2fef 100644 --- a/docs/index.md +++ b/docs/index.md @@ -73,9 +73,23 @@ Requirements: // PyCuVec *PyCuVec_zeros_like(PyCuVec *other); // PyCuVec *PyCuVec_deepcopy(PyCuVec *other); /// returns `NULL` if `self is None`, or - /// `getattr(self, 'cuvec', self)` otherwise + /// `getattr(self, 'cuvec', self)` otherwise: // PyCuVec *asPyCuVec(PyObject *self); // PyCuVec *asPyCuVec(PyCuVec *self); + /// conversion functions for `PyArg_Parse*()` + /// e.g.: `PyArg_ParseTuple(args, "O&", &PyCuVec_f, &obj)`: + // int asPyCuVec_b(PyObject *o, PyCuVec **self); + // int asPyCuVec_B(PyObject *o, PyCuVec **self); + // int asPyCuVec_c(PyObject *o, PyCuVec **self); + // int asPyCuVec_h(PyObject *o, PyCuVec **self); + // int asPyCuVec_H(PyObject *o, PyCuVec **self); + // int asPyCuVec_i(PyObject *o, PyCuVec **self); + // int asPyCuVec_I(PyObject *o, PyCuVec **self); + // int asPyCuVec_q(PyObject *o, PyCuVec **self); + // int asPyCuVec_Q(PyObject *o, PyCuVec **self); + // int asPyCuVec_e(PyObject *o, PyCuVec<__half> **self); + // int asPyCuVec_f(PyObject *o, PyCuVec **self); + // int asPyCuVec_d(PyObject *o, PyCuVec **self); ``` === "C++/SWIG API" @@ -116,7 +130,7 @@ The following involve no memory copies. === "**CPython API** to **C++**" ```cpp - /// input: `PyObject *obj` (obtained from e.g.: `PyArg_ParseTuple()`, etc) + /// input: `PyObject *obj` (obtained from e.g.: `PyArg_Parse*()`, etc) /// output: `CuVec vec` CuVec &vec = ((PyCuVec *)obj)->vec; // like std::vector std::vector &shape = ((PyCuVec *)obj)->shape; @@ -237,11 +251,11 @@ C++: PyCuVec *src = NULL; PyCuVec *dst = NULL; static const char *kwds[] = {"src", "output", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O", (char **)kwds, - (PyObject **)&src, (PyObject **)&dst)) + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O&|O&", (char **)kwds, + &asPyCuVec_f, &src, &asPyCuVec_f, &dst)) return NULL; - src = asPyCuVec(src); - dst = asPyCuVec(dst); + + if (!src) return NULL; From 61188071851d5e06fafb167981cddc43beab76e0 Mon Sep 17 00:00:00 2001 From: Casper da Costa-Luis Date: Mon, 1 Nov 2021 20:04:46 +0000 Subject: [PATCH 9/9] test -Wall --- .github/workflows/test.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0eefb66..3930245 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -55,6 +55,14 @@ jobs: - run: pip install -U -e .[dev] - run: pytest - uses: codecov/codecov-action@v1 + - name: compile -Wall + run: | + git clean -Xdf + pip install toml + python -c 'import toml; c=toml.load("pyproject.toml"); print("\0".join(c["build-system"]["requires"]), end="")' \ + | xargs -0 pip install + python setup.py build -- -DCUVEC_DEBUG=1 \ + -DCMAKE_CXX_FLAGS="-Wall -Wextra -Wpedantic -Werror -Wno-missing-field-initializers -Wno-unused-parameter -Wno-cast-function-type" cuda: if: github.event_name != 'pull_request' || github.repository_owner != 'AMYPAD' name: CUDA py${{ matrix.python }} @@ -71,6 +79,14 @@ jobs: - run: pip install -U -e .[dev] - run: pytest - uses: codecov/codecov-action@v1 + - name: compile -Wall + run: | + git clean -Xdf + pip install toml + python -c 'import toml; c=toml.load("pyproject.toml"); print("\0".join(c["build-system"]["requires"]), end="")' \ + | xargs -0 pip install + python setup.py build -- -DCUVEC_DEBUG=1 \ + -DCMAKE_CXX_FLAGS="-Wall -Wextra -Wpedantic -Werror -Wno-missing-field-initializers -Wno-unused-parameter -Wno-cast-function-type" - name: Post Run setup-python run: setup-python -p${{ matrix.python }} -Dr if: ${{ always() }}