for a university project I want to implement some code in python. Later on, parts of it should be replaced with calls to native CUDA code.
Right now, I was thinking about putting a module wide switch OPTIMIZED in my module.
def set_optimized(b):
# possible check for CUDA device first
OPTIMIZED = b
def my_fun(arg1, arg2):
if OPTIMIZED:
# some c-calls here
return retval
else:
# some python code here
return retval
This implementation has some nice properties:
- Test cases can easily compare optimized and non-optimized versions in result & performance.
- For every optimized function there is a non-optimized backup. For example on machines without CUDA device, I suppress the switch to the optimized version and the programm still runs without changes to the code.
Another option would be to implement all functions as methods of a class NonOpt. The functions could be overriden with optimized versions in class Opt(NonOpt).
It feels like this option has less boilerplate code, but comes with a disadvantage: the algorithm which instantiate and use the class has to be aware of the underlying opt/nonopt versions.
Is there a canonical way to do this? Or is it a bad idea anyway and I'm overlooking something fundamental?
Sidenote: To me this question is quite general. I've stumbled over this problem in the past, when I wanted to maintain optimized and non-optimized code in Julia. Whenerver I had to change the math, I could simply change the easy-readable non-optimized version. The testcases would tell me, wether I've achived the same results in the more complicated optimized version.