Matlab R2018b中C++对TypedArray数组的访问速度慢

3

我正在使用MATLAB R2018b的mex函数将C++库与我的MATLAB代码集成。作为其中的一部分,我需要将MATLAB数组中的数据保存到C++指针数组和C++结构体向量中。然而,映射MATLAB类型数组的速度非常慢(对于约800,000个元素的数组,大约需要0.4秒)。

以下是相关代码:

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]; 
}

什么导致了这个循环变得缓慢?我尝试重新排列顶点的数组访问顺序,以尝试使代码更加缓存友好,但这并没有产生有意义的加速。目前,对于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秒)。有没有其他方法可以加速这个循环呢?


1
Matlab以列为主序存储数据,而C++则以行为主序。因此,这段代码可能会表现出非常糟糕的缓存行为。不过没关系,你已经尝试过了。 - user4581301
1
尝试使用迭代器: auto it = Vertices.begin(); *it; ++it; 等。 这应该比 [] 操作符更有效率,因为后者可能会检查边界等。 详见此处:https://www.mathworks.com/help/matlab/apiref/matlab.data.typedarray.html#d120e11864 和此处:https://www.mathworks.com/help/matlab/apiref/matlab.data.typediterator.html - Cris Luengo
1
我尝试使用迭代器并获得了加速,但仍然出乎意料的慢。 - WStar
1
你可以通过将&*Vertices.begin()传递给你的C++函数来完全避免复制。如果我没记错的话,那应该是一个float const*。如果你需要它可写,请在代码顶部使用非const的TypedArray - Cris Luengo
1个回答

4

我遵循Cris的建议并使用以下代码,从而获得了显著的加速:

const matlab::data::TypedArray<float> Vertices = std::move(inputs[0]);
float* positions = new float[Vertices.getNumberofElements()];
memcpy(positions,&*Vertices.begin,sizeof(float)*Vertices.getNumberofElements());

运行时间从使用标准的Visual Studio优化时的0.14秒缩短到了0.0035秒,这对我的应用程序来说非常快。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接