mne-tools/mne-python — pull request #393 by Eric89GXL (2013-01-17 03:22:11+00:00)
Title: ENH: Speeding up filtering

This simplifies and speeds up the filtering calls (Old/New times listed in seconds on 6-core 3.6 GHz workstation for a ~6 minute, 1000 Hz sampled file):
```
>>> import mne
>>> import time
>>> raw = mne.fiff.Raw('Eric_SoP_001_01_raw_sss.fif', preload=True)
>>> t = time.time(); raw.filter(None, 55, n_jobs=6); print time.time() - t
Old: 118.4 New: 19.9
>>> t = time.time(); raw.filter(None, 55, n_jobs=1); print time.time() - t
Old: 586.9 New: 19.4
>>> t = time.time(); raw.filter(None, 55, n_jobs=6, filter_length=32768); print time.time() - t
Old: 37.9 New: 33.3
>>> t = time.time(); raw.filter(None, 55, n_jobs=1, filter_length=32768); print time.time() - t
Old: 75.6 New: 38.1
```
I think the negligible improvement for more jobs (!) is due to the overhead of pickling that much data, although I'm not 100% sure. @mluessi, any ideas here? In the meantime, it's at least faster than what we had before...

While I was at it, I also added a new feature:
```
>>> t = time.time(); raw.filter(None, 55, n_jobs='cuda'); print time.time() - t
5.2 (compare to 19.4 or 19.9 above)
>>> t = time.time(); raw.filter(None, 55, n_jobs='cuda', filter_length=32768); print time.time() - t
11.0 (compare to 38.1 or 33.3 above)
```
This feature requires installation of `pycuda` and `scikits.cuda` (and of course the underlying CUDA layer), but will gracefully fall back to `n_jobs=1` if these things aren't installed. The ~3-4x speedup is worth these additional dependencies to me. I also have a 2-year old lower-end graphics card, so others may see bigger (or smaller) improvements, depending on hardware. And perhaps most importantly, the additional dependencies are completely optional (@agramfort I know you're concerned about adding dependencies). Plus this way we could say "support for CUDA in filtering raw files", which I think is cool :)

Eventually the CUDA support could also be transformed into OpenCL support for OSX and AMD folks, too, but this was the simplest path. It's also possible that I haven't optimized the CUDA code as much as I could, although I think it's close.