PVMismatch icon indicating copy to clipboard operation
PVMismatch copied to clipboard

[ENH] avoid redundant PVcell property calls

Open kandersolar opened this issue 5 years ago • 0 comments

I've been running some hundreds of millions of iterations of pvmismatch calculations and am interested in optimizing for calculation speed. I noticed that some of the PVcell property methods get called many times for each calcCell() invocation, and it seems to me that all but one of each is redundant. For the test script

import pvmismatch
cell = pvmismatch.PVcell()

here is the profiler results for master:

image

For instance, Isat1 is called 18 times. I tried out a simple caching mechanism that intercepts property calls and only runs the calculations once:

def cached(f):
    def wrapper(self):
        key = f.__name__
        if key in self._cache:
            return self._cache[key]
        value = f(self)
        self._cache[key] = value
        return value
    return wrapper

Which, after adding a _cache = {} definition to the PVcell class and self._cache.clear() to its __setattr__ method, lets you decorate property methods like this:

    @property
    @cached
    def Isat1(self):
        ...

Profiler results using the cache on each of the properties (except looks like I forgot Vt): image

And some timings:

# master
%timeit cell = pvmismatch.PVcell()
227 µs ± 8.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

# cached
%timeit cell = pvmismatch.PVcell()
111 µs ± 2.75 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

I haven't spent enough time with pvmismatch to be sure of all the conditions where the cache should be invalidated, but it seems like there's some potential for speedup with minimally invasive surgery. The code I used for these tests is here: https://github.com/kanderso-nrel/PVMismatch/tree/pvcell_cache

I wanted to get some feedback on the idea before going too far with it. If folks are in support, I'm happy to open a PR.

kandersolar avatar Apr 01 '20 03:04 kandersolar