areaDetector / ADCore

The home of the core components of the EPICS areaDetector software. It includes base classes for drivers and code for all of the standard plugins.
https://areadetector.github.io/master/index.html
Other
20 stars 65 forks source link

Provide a way to override memory allocator for frames #486

Closed EmilioPeJu closed 6 months ago

EmilioPeJu commented 1 year ago

See issue https://github.com/areaDetector/ADCore/issues/487

EmilioPeJu commented 1 year ago

Just let you know that I finished the initial implementation of the AD plugin relying on this feature, it's in https://github.com/dls-controls/ADExternal

sveseli commented 9 months ago

From what it looks like, the changes in this PR will work for what they were intended. However, I believe we already put in place a more general set of interfaces that would allow one to do this (the four methods starting with https://github.com/areaDetector/ADCore/blob/master/ADApp/ADSrc/NDArrayPool.cpp#L56). In the APS DAQ software we have a separate pool class for each type of DAQ object that we need to create and manage (see, for example, https://git.aps.anl.gov/C2/daq/modules/daq-base/-/blob/master/src/pva/daq/pva/PvaNDArrayPool.h#L55). This allows us to use AD framework with our own objects that inherit from NDArray.

EmilioPeJu commented 9 months ago

The thing is ... making a subclass of NDArrayPool would only affect the the plugin instantiating it, and the usual case is not even that, because NDPluginDriver::driverCallback sets this->pNDArrayPool = pArray->pNDArrayPool, which means it uses the NDArrayPool of the original source of the frame.

For my application, I needed to force the source of the frames to use shared memory, the way I proposed will force every plugin and driver to use shared memory and that way my plugin can get frames from anywhere.

@sveseli , unfortunately, I don't have access permission for your link, I assume the buffers allocated by your NDArrayPool subclass were also coming from malloc which limits the applications, if not, how did you workaround the free call inside NDArrayPool::alloc?

@MarkRivers , this is a different problem right? in your case, you want to use special allocation only for the output frame of one plugin, not for everything. It's also an interesting problem, so let's brainstorm a few solutions:

sveseli commented 9 months ago

@EmilioPeJu , if you'd like, we could probably get you read access to APS DAQ repositories, just send me email.

In our case, we do not really use internal NDArray buffer, but instead create our own objects that are destroyed when the delete is called. The IOC driver instantiates the appropriate pool class, not individual plugins (see, for example https://git.aps.anl.gov/C2/daq/iocs/daq-ps-ioc/-/blob/master/src/driver/PsDaqDriver.cpp?ref_type=heads#L339).

Looking at the NDArrayPool code again, I think you are right, there should be additional hooks that that would hide malloc/free calls.

EmilioPeJu commented 9 months ago

OK, I've amended my commit and provided a hook to locally override the frame buffer allocation and deallocation functions. The functions that you would override in a subclass are frameMalloc and frameFree. I still keep the function to override the default malloc and free functions (which I need) but now I've made the setter function a static method of NDArrayPool called setDefaultFrameMemoryFunctions. I've also renamed a few things to be consistent with the rest and I hope the code looks cleaner now.