C++ MEX Data API: How can I get the raw pointer of an array input without copying it?

19 次查看(过去 30 天)
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 个评论
James Tursa
James Tursa 2021-10-31
Do you need the C++ API functionality? Maybe consider going the mexFunction( ) route where getting the data pointers is trivial.
Petros Arvanitis
Petros Arvanitis 2021-10-31
编辑:Petros Arvanitis 2022-3-20
This is what I'm currently doing (mexFunction). I was just reading in the documentation that it's better to take the C++ API route for some reason, but I guess I will just use mexFunction () if there is no solution. It seems strange though, that there is no way to do this in the C++ API.

请先登录,再进行评论。

采纳的回答

dhyun
dhyun 2022-3-18
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.

更多回答(1 个)

Nathan
Nathan 2023-10-9
编辑:Nathan 2023-10-9
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!

类别

Help CenterFile Exchange 中查找有关 MATLAB Data API for C++ 的更多信息

产品


版本

R2019a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by