MEX-функции часто могут улучшить эффективность, управляя, когда функция делает копии больших массивов данных. Вы можете избежать ненужных копий массивов в следующих случаях:
MEX-функция обращается к входу массиву, но элементы массива не изменяются.
Эта MEX-функция изменяет массив входа, и измененный массив возвращается к функции вызова.
Эта MEX-функция суммирует элементы входного массива, но не изменяет массив. Назначение inputs[0]
в const
matlab::data::TypedArray<double>
переменная позволяет использовать основанную на диапазоне for
цикл для суммирования элементов. Определение массива следующим const
обеспечивает переменную inArray
остается общим с массивом входа.
#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);
}
};
После сохранения этого кода в файле (называется addArrayElements.cpp
в этом примере), скомпилируйте его с mex
функция. Вызовите эту MEX-функцию из MATLAB® с двойным массивом в качестве входного параметра.
mex addArrayElements.cpp
b = addArrayElements([1:1e7]);
b =
5.0000e+13
Эта MEX-функция заменяет отрицательные значения в массиве входа нулями. Эта операция изменяет входной массив, поэтому вход не может оставаться общим с измененным массивом. После проверки массива входа функция не использует inputs[0]
снова. Поэтому проверенная inputs[0]
массив перемещается в matlab::data::TypedArray<double>
переменная, позволяющая использовать основанную на диапазоне for
цикл для изменения элементов массива.
Чтобы предотвратить копию входного массива, перемещайте input[0]
в matlab::data::TypedArray<double>
использование std::move()
, который меняет память, связанную с массивом входа, на переменную 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") }));
}
}
};
После сохранения этого кода в файле (называется removeNegativeNumbers.cpp
в этом примере), скомпилируйте его с mex
функция.
mex removeNegativeNumbers.cpp
Вызовите эту MEX-функцию из функции MATLAB. Переназначите измененный массив той же переменной.
function arry = processArray(arry) arry = removeNegativeNumbers(arry); .... end
Для примера вызовите processArray
функция с большим массивом, возвращенным MATLAB randn
функция.
A = processArray(randn(10000)); min(A(:)) ans = 0