lebedov/scikits.cuda — pull request #88 by grlee77 (2014-12-08 17:06:11+00:00)
Title: WIP:  ENH: full set of cuSPARSE wrappers via CFFI with a limited set of higher-level interface routines

Hi @lebedov,
I saw that you and @untom had started wrapping cusparse via CFFI, but it didn't look like it had been updated recently. Last week, I needed some CSR routines and looked into CFFI for wrapping them. I figured that if I could autogenerate the wrappers from the header file then it would be nearly as easy to just wrap everything instead. I had never used CFFI previously, but based on your example code in the cffi branch on how to pass the complex data types, etc., I was able to get it to work.

Thank you for your work on the scikits.cuda package. I hope you will find these wrappers to be of use and that after some tweaking that they can eventually be merged into the package.

**This pull request differs from what is in your cffi branch in a couple of ways:**
1.) I am using the API approach in cffi by passing in text extracted from the cusparse header file rather
than using the library ABI. By reading in the full header, all routines present will get wrapped. The drawback is that compilation is required. This will currently be done upon the first import of `scikits.cuda.cusparse`

2.) I then made a crude parser/string replacement code that goes through each C function declaration and generates the python wrapper (including docstrings) for each function in the cusparse library
see `_cusparse_cffi.py` and the supporting routines for `_cusparse_cffi_autogen.py` for how this part is done. This part works on my machine with CUDA v6.5 and 64-bit linux, but will likely still need a bit of tweaking for other platforms and/or older CUDA versions. Anyone better at string parsing could probably simplify/improve this part considerably.

3.) Once all the low-level functions had been wrapped, I then wrapped some of the ones I intend to use in higher level python functions that will call the function for the appropriate datatype, etc. These higher level wrappers as well as an example CSR class are implemented in `cusparse.py`.

Specifically, there are simplified, data-type agnostic wrappers for the following routines:

**Level2 functions:**
csrmv

**Level3 functions:**
csrmm
csrmm2

**extra functions:**
csrgeam
csrgemm

**conversions:**
csc2coo
csc2dense
csr2coo
csr2csc
csr2dense
coo2csc
coo2csr
dense2csc
dense2csr
nnz

I found that it is very easy to get the arguments or data ordering wrong (e.g. cuSPARSE expects dense matrices to be column-major, etc.) when using the low level functions, so these wrappers and the checks they perform greatly simplify things.

5.) There are also tests for a subset of the routines (particularly the specific ones wrapped above) within `tests/test_cusparse.py`. These can be run via `nosetests`, but they are not currently implemented as small individual unit tests like I saw in the other test_*.py files.

6.) See also CSR object example I put in the comments to #44