Skip to content

Commit

Permalink
swig: remove SwigCuVec alias in favour of NDCuVec
Browse files Browse the repository at this point in the history
  • Loading branch information
casperdcl committed Feb 25, 2024
1 parent 68c098b commit 6722d42
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 54 deletions.
10 changes: 2 additions & 8 deletions cuvec/include/cuvec.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,8 @@
* Pure CUDA/C++11 template header. Provides:
* - CuVec<T> // analogous to `std::vector` but using CUDA unified memory
*
* pybind11 helpers wrapping `CuVec<T>`. Provides:
* Helpers wrapping `CuVec<T>`. Provides:
* - NDCuVec<T> // contains `CuVec<T> vec` and `std::vector<size_t> shape`
*
* SWIG helpers wrapping `CuVec<T>`. Provides:
* - SwigCuVec<T> // contains `CuVec<T> vec` and `std::vector<size_t> shape`
*/
#ifndef _CUVEC_H_
#define _CUVEC_H_
Expand Down Expand Up @@ -99,7 +96,7 @@ template <class T> using CuVec = std::vector<T, CuAlloc<T>>;
#endif // CUVEC_DISABLE_CUDA
#endif // _CUVEC_HALF

/// pybind11 helpers
/// external wrapper helper
template <class T> struct NDCuVec {
CuVec<T> vec;
std::vector<size_t> shape;
Expand All @@ -123,7 +120,4 @@ template <class T> struct NDCuVec {
}
};

/// SWIG helpers
template <class T> using SwigCuVec = NDCuVec<T>;

#endif // _CUVEC_H_
6 changes: 3 additions & 3 deletions cuvec/include/cuvec.i
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
/**
* SWIG template header wrapping `SwigCuVec<T>` as defined in "cuvec.cuh"
* SWIG template header wrapping `NDCuVec<T>` as defined in "cuvec.cuh"
* for external use via `%include "cuvec.i"`.
*/
%include "std_vector.i"
%{
#include "cuvec.cuh" // SwigCuVec<T>
#include "cuvec.cuh" // NDCuVec<T>
%}
/// expose definitions
template <class T> struct SwigCuVec {
template <class T> struct NDCuVec {
CuVec<T> vec;
std::vector<size_t> shape;
};
38 changes: 19 additions & 19 deletions cuvec/src/cuvec_swig.i
Original file line number Diff line number Diff line change
Expand Up @@ -9,39 +9,39 @@
}
}

%include "cuvec.i" // SwigCuVec<T>
%include "cuvec.i" // NDCuVec<T>

%{
template <class T> SwigCuVec<T> *SwigCuVec_new(std::vector<size_t> shape) {
SwigCuVec<T> *self = new SwigCuVec<T>(shape);
template <class T> NDCuVec<T> *NDCuVec_new(std::vector<size_t> shape) {
NDCuVec<T> *self = new NDCuVec<T>(shape);
return self;
}
template <class T> void SwigCuVec_del(SwigCuVec<T> *self) {
template <class T> void NDCuVec_del(NDCuVec<T> *self) {
self->~NDCuVec();
delete self;
}
template <class T> size_t SwigCuVec_address(SwigCuVec<T> *self) {
template <class T> size_t NDCuVec_address(NDCuVec<T> *self) {
return (size_t)self->vec.data();
}
template <class T> std::vector<size_t> SwigCuVec_shape(SwigCuVec<T> *self) { return self->shape; }
template <class T> void SwigCuVec_reshape(SwigCuVec<T> *self, const std::vector<size_t> &shape) {
template <class T> std::vector<size_t> NDCuVec_shape(NDCuVec<T> *self) { return self->shape; }
template <class T> void NDCuVec_reshape(NDCuVec<T> *self, const std::vector<size_t> &shape) {
self->reshape(shape);
}
%}
template <class T> SwigCuVec<T> *SwigCuVec_new(std::vector<size_t> shape);
template <class T> void SwigCuVec_del(SwigCuVec<T> *self);
template <class T> size_t SwigCuVec_address(SwigCuVec<T> *self);
template <class T> std::vector<size_t> SwigCuVec_shape(SwigCuVec<T> *self);
template <class T> void SwigCuVec_reshape(SwigCuVec<T> *self, const std::vector<size_t> &shape);
template <class T> NDCuVec<T> *NDCuVec_new(std::vector<size_t> shape);
template <class T> void NDCuVec_del(NDCuVec<T> *self);
template <class T> size_t NDCuVec_address(NDCuVec<T> *self);
template <class T> std::vector<size_t> NDCuVec_shape(NDCuVec<T> *self);
template <class T> void NDCuVec_reshape(NDCuVec<T> *self, const std::vector<size_t> &shape);

%template(SwigCuVec_Shape) std::vector<size_t>;
%template(NDCuVec_Shape) std::vector<size_t>;
%define MKCUVEC(T, typechar)
%template(SwigCuVec_ ## typechar) SwigCuVec<T>;
%template(SwigCuVec_ ## typechar ## _new) SwigCuVec_new<T>;
%template(SwigCuVec_ ## typechar ## _del) SwigCuVec_del<T>;
%template(SwigCuVec_ ## typechar ## _address) SwigCuVec_address<T>;
%template(SwigCuVec_ ## typechar ## _shape) SwigCuVec_shape<T>;
%template(SwigCuVec_ ## typechar ## _reshape) SwigCuVec_reshape<T>;
%template(NDCuVec_ ## typechar) NDCuVec<T>;
%template(NDCuVec_ ## typechar ## _new) NDCuVec_new<T>;
%template(NDCuVec_ ## typechar ## _del) NDCuVec_del<T>;
%template(NDCuVec_ ## typechar ## _address) NDCuVec_address<T>;
%template(NDCuVec_ ## typechar ## _shape) NDCuVec_shape<T>;
%template(NDCuVec_ ## typechar ## _reshape) NDCuVec_reshape<T>;
%enddef
MKCUVEC(signed char, b)
MKCUVEC(unsigned char, B)
Expand Down
6 changes: 3 additions & 3 deletions cuvec/src/example_swig/example_swig.cu
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* Copyright (2021) Casper da Costa-Luis
*/
#include "cuvec.cuh" // SwigCuVec
#include "cuvec.cuh" // NDCuVec
#include <stdexcept> // std::length_error
#ifdef CUVEC_DISABLE_CUDA
#include <chrono> // std::chrono
Expand All @@ -17,7 +17,7 @@ __global__ void _d_incr(float *dst, float *src, int X, int Y) {
dst[y * X + x] = src[y * X + x] + 1;
}
#endif // CUVEC_DISABLE_CUDA
SwigCuVec<float> *increment2d_f(SwigCuVec<float> &src, SwigCuVec<float> *output, bool timing) {
NDCuVec<float> *increment2d_f(NDCuVec<float> &src, NDCuVec<float> *output, bool timing) {
auto &N = src.shape;
if (N.size() != 2) throw std::length_error("`src` must be 2D");

Expand All @@ -32,7 +32,7 @@ SwigCuVec<float> *increment2d_f(SwigCuVec<float> &src, SwigCuVec<float> *output,
#endif

if (!output)
output = new SwigCuVec<float>(N);
output = new NDCuVec<float>(N);
else if (N != output->shape)
throw std::length_error("`output` must be same shape as `src`");

Expand Down
6 changes: 3 additions & 3 deletions cuvec/src/example_swig/example_swig.i
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
}
}

%include "cuvec.i" // SwigCuVec<T>
%include "cuvec.i" // NDCuVec<T>
%{
/// signatures from "example_swig.cu"
SwigCuVec<float> *increment2d_f(SwigCuVec<float> &src, SwigCuVec<float> *output = NULL, bool timing = false);
NDCuVec<float> *increment2d_f(NDCuVec<float> &src, NDCuVec<float> *output = NULL, bool timing = false);
%}
/// expose definitions
SwigCuVec<float> *increment2d_f(SwigCuVec<float> &src, SwigCuVec<float> *output = NULL, bool timing = false);
NDCuVec<float> *increment2d_f(NDCuVec<float> &src, NDCuVec<float> *output = NULL, bool timing = false);
16 changes: 8 additions & 8 deletions cuvec/swig.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@
'typecodes']

log = logging.getLogger(__name__)
if hasattr(sw, 'SwigCuVec_e_new'):
if hasattr(sw, 'NDCuVec_e_new'):
typecodes += 'e'


class SWIGVector(CVector):
RE_CUVEC_TYPE = re.compile("<.*SwigCuVec_(.); proxy of <Swig Object of type"
r" 'SwigCuVec<\s*(\w+)\s*>\s*\*' at 0x\w+>")
RE_CUVEC_TYPE = re.compile("<.*NDCuVec_(.); proxy of <Swig Object of type"
r" '(?:ND|Swig)CuVec<\s*(\w+)\s*>\s*\*' at 0x\w+>")

def __init__(self, typechar: str, shape: Shape, cuvec=None):
"""
Expand All @@ -38,27 +38,27 @@ def __init__(self, typechar: str, shape: Shape, cuvec=None):
"""
if cuvec is None:
shape = shape if isinstance(shape, Sequence) else (shape,)
cuvec = getattr(sw, f'SwigCuVec_{typechar}_new')(shape)
cuvec = getattr(sw, f'NDCuVec_{typechar}_new')(shape)
else:
typechar = self.is_raw_cuvec(cuvec).group(1)
self.cuvec = cuvec
super().__init__(typechar)

def __del__(self):
getattr(sw, f'SwigCuVec_{self.typechar}_del')(self.cuvec)
getattr(sw, f'NDCuVec_{self.typechar}_del')(self.cuvec)

@property
def shape(self) -> tuple:
return getattr(sw, f'SwigCuVec_{self.typechar}_shape')(self.cuvec)
return getattr(sw, f'NDCuVec_{self.typechar}_shape')(self.cuvec)

@shape.setter
def shape(self, shape: Shape):
shape = shape if isinstance(shape, Sequence) else (shape,)
getattr(sw, f'SwigCuVec_{self.typechar}_reshape')(self.cuvec, shape)
getattr(sw, f'NDCuVec_{self.typechar}_reshape')(self.cuvec, shape)

@property
def address(self) -> int:
return getattr(sw, f'SwigCuVec_{self.typechar}_address')(self.cuvec)
return getattr(sw, f'NDCuVec_{self.typechar}_address')(self.cuvec)


SWIGVector.vec_types = {np.dtype(c): partial(SWIGVector, c) for c in typecodes}
Expand Down
20 changes: 10 additions & 10 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ Requirements:
=== "SWIG"
```cpp
#include "cuvec.cuh"
SwigCuVec<float> *swv = new SwigCuVec<float>({1337, 42});
NDCuVec<float> *ndv = new NDCuVec<float>({1337, 42});
```

=== "CUDA"
Expand Down Expand Up @@ -203,10 +203,10 @@ The following involve no memory copies.

=== "to C++"
```cpp
/// input: `SwigCuVec<type> *swv`
/// input: `NDCuVec<type> *ndv`
/// output: `CuVec<type> vec`, `std::vector<size_t> shape`
CuVec<float> &vec = swv->vec; // like std::vector<float>
std::vector<size_t> &shape = swv->shape;
CuVec<float> &vec = ndv->vec; // like std::vector<float>
std::vector<size_t> &shape = ndv->shape;
```

=== "C & CUDA"
Expand Down Expand Up @@ -404,8 +404,8 @@ C++:
%{
#include "mycudafunction_swig.h"
%}
SwigCuVec<float> *myfunc(
SwigCuVec<float> &src, SwigCuVec<float> *output = NULL);
NDCuVec<float> *myfunc(
NDCuVec<float> &src, NDCuVec<float> *output = NULL);



Expand Down Expand Up @@ -495,12 +495,12 @@ CUDA:
=== "SWIG"
```{.cpp linenums="1"}
#include "cuvec.cuh"
SwigCuVec<float> *myfunc(
SwigCuVec<float> &src, SwigCuVec<float> *output = NULL) {
NDCuVec<float> *myfunc(
NDCuVec<float> &src, NDCuVec<float> *output = NULL) {
// hardcode upsampling factor 2
std::vector<size_t> shape = src.shape;
for (auto &i : shape) i *= 2;
if (!output) output = new SwigCuVec<float>(shape);
if (!output) output = new NDCuVec<float>(shape);
mykernel<<<...>>>(output->vec.data(), src.vec.data(),
shape[0], shape[1], shape[2]);
cudaDeviceSynchronize();
Expand All @@ -521,7 +521,7 @@ See also [NumCu](https://github.com/AMYPAD/NumCu), a minimal stand-alone Python
=== "Python"
Python objects (`arr`, returned by `cuvec.zeros()`, `cuvec.asarray()`, or `cuvec.copy()`) contain all the attributes of a `numpy.ndarray`. Additionally, `arr.cuvec` implements the [buffer protocol](https://docs.python.org/3/c-api/buffer.html), while `arr.__cuda_array_interface__` (and `arr.__array_interface__`) provide [compatibility with other libraries](https://numba.readthedocs.io/en/latest/cuda/cuda_array_interface.html) such as Numba, CuPy, PyTorch, PyArrow, and RAPIDS.

When using the SWIG alternative module, `arr.cuvec` is a wrapper around `SwigCuVec<type> *`.
When using the SWIG alternative module, `arr.cuvec` is a wrapper around `NDCuVec<type> *`.

=== "C++/pybind11/CUDA"
`cuvec` is a header-only library so simply do one of:
Expand Down

0 comments on commit 6722d42

Please sign in to comment.