Skip to content

[ENH] avoid redundant PVcell property calls #121

@kandersolar

Description

@kandersolar

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions