Avoid Copies of Arrays in MEX Functions
MEX functions often can improve performance by controlling when the function makes copies of large data arrays. You can avoid unnecessary copies of arrays in these cases:
The MEX function accesses an input array, but the elements of the array are not modified.
The MEX function modifies an input array and the modified array is returned to the calling function.
If you are writing MATLAB® code instead of C++ applications, see Avoid Unnecessary Copies of Data.
Input Array Not Modified
This MEX function sums the elements of the input array, but does not modify the
array. Assigning inputs[0]
to a const
matlab::data::TypedArray<double>
variable lets you use a range-based for
loop to sum the elements.
Specifying the array as const
ensures the variable
inArray
remains shared with the input array.
#include "mex.hpp"
#include "mexAdapter.hpp"
using namespace matlab::data;
using matlab::mex::ArgumentList;
class MexFunction : public matlab::mex::Function {
ArrayFactory factory;
public:
void operator()(ArgumentList outputs, ArgumentList inputs) {
double sm = 0;
const TypedArray<double> inArray = inputs[0];
for (auto& elem : inArray) {
sm += elem;
}
outputs[0] = factory.createScalar(sm);
}
};
After saving this code in a file (called addArrayElements.cpp
in this example), compile it with the mex
function. Call this MEX
function from MATLAB with a double array as the input argument.
mex addArrayElements.cpp
b = addArrayElements([1:1e7]);
b =
5.0000e+13
Input Array Modified
This MEX function replaces negative values in the input array with zeros. This
operation modifies the input array so the input cannot remain shared with the
modified array. After validating the input array, the function does not use
inputs[0]
again. Therefore, the validated
inputs[0]
array is moved to a matlab::data::TypedArray<double>
variable to enable the use of a range-based for
loop to modify
the array elements.
To prevent a copy of the input array, move input[0]
to a matlab::data::TypedArray<double>
using std::move()
, which swaps the memory associated with the
input array to the variable largeArray
.
#include "mex.hpp"
#include "mexAdapter.hpp"
using namespace matlab::data;
using matlab::mex::ArgumentList;
class MexFunction : public matlab::mex::Function {
public:
void operator()(ArgumentList outputs, ArgumentList inputs) {
checkArguments(inputs);
TypedArray<double> largeArray = std::move(inputs[0]);
for (auto& elem : largeArray) {
if (elem < 0) {
elem = 0;
}
}
outputs[0] = largeArray;
}
void checkArguments(ArgumentList inputs) {
std::shared_ptr<matlab::engine::MATLABEngine> matlabPtr = getEngine();
ArrayFactory factory;
if (inputs[0].getType() != ArrayType::DOUBLE ||
inputs[0].getType() == ArrayType::COMPLEX_DOUBLE) {
matlabPtr->feval(u"error", 0,
std::vector<Array>({ factory.createScalar("Incorrect input") }));
}
}
};
After saving this code in a file (called
removeNegativeNumbers.cpp
in this example), compile it with
the mex
function.
mex removeNegativeNumbers.cpp
Call this MEX function from a MATLAB function. Reassign the modified array to the same variable.
function arry = processArray(arry) arry = removeNegativeNumbers(arry); .... end
For example, call the processArray
function with a large array
returned by the MATLAB
randn
function.
A = processArray(randn(10000)); min(A(:)) ans = 0