【发布时间】:2018-11-05 19:59:16
【问题描述】:
我正在使用 MATLAB R2018b mex 函数将 C++ 库与我的 MATLAB 代码集成。作为其中的一部分,我需要在 MATLAB 数组中获取数据并保存到 C++ 指针数组和 C++ 结构向量中。但是,映射 matlab 类型的数组被证明非常慢(约 0.4 秒,约 800,000 个元素)。
这里是相关代码
const matlab::data::TypedArray<float> Vertices = std::move(inputs[0]);
float* positions = new float[Vertices.getNumberofElements()];
for (size_t i = 0; i < Vertices.getDimensions()[0]; i ++)
{
ctr = 9 * i;
positions[ctr + 0] = Vertices[i][0];
positions[ctr + 1] = Vertices[i][1];
positions[ctr + 2] = Vertices[i][2];
}
是什么导致这个循环变慢?我尝试为 Vertices 重新排序数组访问以尝试使代码对缓存更友好,但这并没有产生有意义的加速。现在,800,000 个元素的循环约为 0.4 毫秒,理想情况下,内存复制应该花费更少的时间,对吧?
当我查看之前的建议时,我发现大多数答案都使用较旧的 mex 函数,而新的(?) MATLAB C++ API 没有相同的函数或结构。
编辑:
我听从 Cris 的建议,并在迭代器上使用了循环,这将速度提高了大约一半,达到 0.14 秒。
我正在使用的新代码是:
const matlab::data::TypedArray<float> Vertices = std::move(inputs[0]);
float* positions = new float[Vertices.getNumberofElements()];
for (auto it = Vertices.begin(); it != Vertices.end(); ++it)
{
positions[ctr] = *it;
++ctr;
}
所以它更快,但仍然非常慢(800,000 个元素为 0.14 秒)。有没有其他方法可以加快这个循环?
【问题讨论】:
-
Matlab 以 Column-Major 顺序存储数据。 C++ 需要 Row-Major。结果,此代码可能表现出非常差的缓存行为。没关系。你已经试过了。
-
尝试使用迭代器:
auto it = Vertices.begin(); *it; ++it;等。这应该比[]运算符更有效,后者可能会检查边界等等。见这里:mathworks.com/help/matlab/apiref/… 和这里:mathworks.com/help/matlab/apiref/matlab.data.typediterator.html -
我尝试使用迭代器并获得了加速,但仍然非常慢。
-
您可以通过将
&*Vertices.begin()传递给您的C++ 函数来完全避免复制。如果我猜对了,那应该是float const*。如果您需要它可写,请在代码顶部使用非常量TypedArray。