Avoid Copies of Arrays in MEX Functions - MATLAB & Simulink (original) (raw)

Main Content

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:

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 variable lets you use a range-based for loop to sum the elements. Specifying the array as const ensures the variableinArray 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 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 useinputs[0] again. Therefore, the validatedinputs[0] array is moved to a matlab::data::TypedArray 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 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 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 (calledremoveNegativeNumbers.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 MATLABrandn function.

A = processArray(randn(10000)); min(A(:))

ans =

 0