Object-specific allocator for cv::Mat

Does OpenCV support object-specific allocators for cv::Mat class?

I’m using OpenCV’s GPU routines and would like to allocate some of the cv::Mat objects using pinned memory. As per this link, I can call the cv::Mat::setDefaultAllocator() routine to use pinned memory, but that routine is a static member that will make all Mat objects use pinned memory, correct?

As an alternative to using cv::Mat::setDefaultAllocator(), I looked into setting the public “allocator” attribute of a Mat object. But as per this Github issue, the allocator attribute is not really used.

Is there any other way I can set the allocator for specific Mat objects?

You could allocate and then pin the memory afterwards using void cv::cuda::registerPageLocked ( Mat& m ) or just use cv::cuda::HostMem directly.

1 Like

Thanks - using cv::cuda::registerPageLocked ( Mat& m ) worked! Using pinned memory improved the performance of my application by 47%.

Out of curiosity, I tried cv::Mat::setDefaultAllocator() also, but that had no effect on performance. The exact call I had in my application was:

cv::Mat::setDefaultAllocator(cv::cuda::HostMem::getAllocator(cv::cuda::HostMem::AllocType::PAGE_LOCKED));

Is there an issue with this OpenCV routine, or am I missing something? The OpenCV version I’m using is 4.5.3.

That’s great glad I could help! I find cv::cuda::HostMem is better if you can use it because you don’t need to remember to call cv::cuda::unregisterPageLocked() when your done.

I wouldn’t have thought there would be an issue with that version of OpenCV. I just confirmed on the master that changing the allocater forced all alocations of cv::Mat to be pinned. If you have built a debug version I would check that this line is hit

when allocating new cv::Mat’s after changing the default allocator.

1 Like

Thanks! Confirming that cv::Mat::setDefaultAllocator() not working for me was an error on my part. Resolved now.

One clarification: pinning with cv::cuda::HostMem is useful only when new cv::Mat objects are allocated, correct? And you have to know the size and type of the allocation also? For example, if I want a pinned cv::Mat after a call to cv::imdecode(), I cannot use cv::cuda::HostMem, unless I know in advance the size and type of the image being decoded?

I would guess from the function signature

cv::imdecode (InputArray buf, int flags, Mat *dst)

that you can’t pass a HostMem object as dst because it is a Mat and not an OutputArray. That said I know VideoCapture::read works and I would expect all functions which the output is an OutputArray to allow you to pass in an empty HostMem object and internally alocate it for you.

1 Like