Last active
November 2, 2017 13:47
-
-
Save eldstal/ab64720e428db5c87093d1589899788f to your computer and use it in GitHub Desktop.
Numpy C++ module
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
all: nativemodule.so | |
%.so: %.cpp | |
g++ -ggdb -std=c++11 -shared -I/usr/include/python2.7 -lpython2.7 -fPIC -o $@ $< | |
run: nativemodule.so | |
./run.py |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Native implementations of some functions for tighter type control | |
*/ | |
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION | |
#include <Python.h> | |
#include "numpy/arrayobject.h" | |
#include <cstdint> | |
#include <string> | |
#include <sstream> | |
#include <ctime> | |
#include <iostream> | |
using std::cerr; | |
using std::string; | |
using std::endl; | |
void doStuff(double * in, long int inh, long int inw, | |
double * out, long int outh, long int outw) { | |
// Just repeat the input array over and over again into the larger output | |
for (int r=0; r<outh; ++r) { | |
for (int c=0; c<outw; ++c) { | |
size_t index = r * outw + c; | |
size_t in_index = index % (inh*inw); | |
out[index] = in[in_index]; | |
} | |
} | |
} | |
/** | |
* Sizzle and swizzle a numpy array | |
* This is called directly from python. | |
* Parameter: input array, 2-dimensional | |
* Parameter: h, the desired output height | |
* Parameter: w, the desired output width | |
* | |
* The input array must be smaller or equal to hxw. | |
* The return value (numpy array of doubles) is hxw. | |
*/ | |
static PyObject* py_dostuff(PyObject* self, PyObject* args) | |
{ | |
PyObject* in_thumb; | |
long int out_dims[2]; // h, w | |
/* parse numpy arguments. Object, Long, Long: Oll */ | |
if (!PyArg_ParseTuple(args, "Oll", | |
&in_thumb, | |
&out_dims[0], | |
&out_dims[1])) { | |
cerr << "Unable to parse arguments. " << endl; | |
return NULL; | |
} | |
// Figure out the shape of the input array | |
PyArrayObject* thumb_array = (PyArrayObject*) PyArray_FromAny(in_thumb, | |
NULL, | |
2, 2, | |
NPY_ARRAY_CARRAY_RO, | |
0); | |
int ndims = PyArray_NDIM(thumb_array); | |
long int* dims = PyArray_DIMS(thumb_array); | |
if (ndims != 2) { | |
cerr << "Non-2D array passed to upsample_fixp." << endl; | |
return NULL; | |
} | |
long int thumb_h = dims[0]; | |
long int thumb_w = dims[1]; | |
// TODO: assert that in_thumb.dtype is double | |
long int origin[2] = {0, 0}; | |
// Get a 1D C array that refers directly to our source data as inarray[y*w + x] | |
double* inarray; | |
inarray = (double*) PyArray_GetPtr(thumb_array, origin); | |
// Create a numpy array of floats where our results go | |
PyArrayObject* ret = (PyArrayObject*) PyArray_SimpleNew(2, out_dims, NPY_DOUBLE); | |
// Get a C-mapping retdata[y*w + x] where we can write stuff into the numpy array | |
double* retdata; | |
retdata = (double*) PyArray_GetPtr(ret, origin); | |
// Here's the computational kernel. Compute, write to retdata and enjoy. | |
doStuff(inarray, thumb_h, thumb_w, retdata, out_dims[0], out_dims[1]); | |
// Return the numpy array back to the python caller | |
return PyArray_Return(ret); | |
} | |
/* | |
* Bind Python function names to our C functions | |
*/ | |
static PyMethodDef native_methods[] = { | |
{"dostuff", py_dostuff, METH_VARARGS}, | |
{NULL, NULL} | |
}; | |
/* | |
* Python calls this to let us initialize our module | |
*/ | |
PyMODINIT_FUNC | |
initnative() | |
{ | |
(void) Py_InitModule("native", native_methods); | |
import_array(); | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/env python2 | |
import numpy | |
import native | |
in_array = numpy.ndarray((2, 4)) | |
in_array[0,:] = [ 1, 2 , 4, 8 ] | |
in_array[1,:] = [ 256, 128, 64, 32 ] | |
print in_array | |
upscaled = native.dostuff(in_array, 10, 10) | |
print upscaled |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment