C++ MEX Data API: How can I get the raw pointer of an array input without copying it?
19 views (last 30 days)
Show older comments
I have an application which constantly calls C++ code from MATLAB, providing it with a large array input, from which I need the raw pointer. Because of the nature of the application, I cannot afford the time cost of copying this array on every call. Also, the array remains unmodified, meaning that the copying is completely redundant.
Here is a minimal reproduction code:
#include "mex.hpp"
#include "mexAdapter.hpp"
#include <chrono>
using namespace matlab::data;
class MexFunction : public matlab::mex::Function {
public:
void operator()(matlab::mex::ArgumentList outputs, matlab::mex::ArgumentList inputs)
{
TypedArray<double> inArr(inputs[0]); //% get input array
//% time getting raw pointer
auto start = std::chrono::steady_clock::now();
auto ptr = inArr.release().get(); //% get raw pointer
auto stop = std::chrono::steady_clock::now();
auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(stop - start);
auto elapsed_time = diff.count();
std::cout << "Getting the raw pointer took " << elapsed_time << " milliseconds.\n";
}
};
This code can be compiled using mex and called from MATLAB as follows:
A = randn(1000000, 128); % create large array
main(A); % call mex function with A as input
Timing this operation, I noticed that it took almost half a second, which implies copying the array.
I also tried using the following line, instead, to get the raw pointer, but again a copy was made:
auto ptr = &*inArr.begin();
I assume that the array is shared with MATLAB, thus a copy is forced every time.
Is there a way to get the raw pointer through the MEX Data API without forcing a copy of the data?
If not, is there a way to directly get the raw pointer from the input array without using the MEX Data API functions? I guess not.
2 Comments
James Tursa
on 31 Oct 2021
Do you need the C++ API functionality? Maybe consider going the mexFunction( ) route where getting the data pointers is trivial.
Accepted Answer
dhyun
on 18 Mar 2022
This is a few months late, but I finally found a good solution to this problem:
#include "MatlabDataArray.hpp"
template <typename T>
const T* getDataPtr(matlab::data::Array arr) {
const matlab::data::TypedArray<T> arr_t = arr;
matlab::data::TypedIterator<const T> it(arr_t.begin());
return it.operator->();
}
For instance, if the first argument in your void operator() function is an array of doubles, you can use
auto ptr = getDataPtr<double>(inputs[0]);
to get the pointer without a deep copy.
I'm surprised that the C++ API makes it so difficult to perform essential functions like accessing raw pointers, especially when that is the primary use case for MEX functions (for me, anyway). Then again, maybe we should just be grateful that a C++ API exists at all.
More Answers (1)
Nathan
on 9 Oct 2023
Edited: Nathan
on 9 Oct 2023
Hi there! Turns out there's another way to do this, that's faster for large arrays, although you need to know the number of dimensions for the array. For example, if you had a 2D double array as an input:
using namespace matlab::data;
TypedArray<double> double_array2d = std::move(inputs[0]);
double* ptr = & double_array2d[0][0].operator double &();
//do something in a loop using pointers!
for (int ii = 0; ii < my_array.getNumberOfElements(); ++ii) {
*ptr += 1; // or whatever
}
You can use this on arrays with more dimensions, just include the appropriate number of [0]'s when indexing. Just be careful with row/column major ordering!
See Also
Categories
Find more on MATLAB Data API for C++ in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!