Main Content

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.

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

Related Topics