如何进一步优化这个循环
how do I optimize this loop further?
嗯,这篇文章是为什么memcpy()和memmove()比指针增量更快的原因?
我有一个带有4个通道的自定义图像结构,我喜欢将其中3个(RGB)提取到具有3个通道的openCV cv::MAt结构中。
cv::Mat GetColorImgFromFrame(Image* pimg)
{
int iHeight = pimg->m_imageInfo.m_height;
int iWidth = pimg->m_imageInfo.m_width;
cv::Mat cvmColorImg = cv::Mat::zeros(iHeight, iWidth, CV_8UC3);
int iDestStep = cvmColorImg.channels(); // 3
uchar* pucSrc = pimg->m_data;
uchar* pucDest = cvmColorImg.data;
uchar* pucDestLimit = cvmColorImg.data + iHeight*iWidth*iDestStep;
for (;pucDest < pucDestLimit;)
{
*(pucDest++) = *(pucSrc++);
*(pucDest++) = *(pucSrc++);
*(pucDest++) = *(pucSrc++);
pucSrc++;
}
return cvmColorImg;
}
用memcpy(pucDest, pucSrc, 3)代替三个内部赋值似乎没有多大帮助。有什么建议吗?
在使用SIMD intrinsic进入"assembler like"模式之前,您可以尝试告诉编译器源指针和目标指针不别名,例如使用gcc的__restrict__
关键字或visual studio的__restrict
关键字
在32位机器上,您可以尝试使用unsigned int *
从源到目标每个循环一次复制4字节。诀窍是保持pucDest
和uchar
指针增加3。您必须将最后一个单词作为特殊情况处理,以免最后一个字节违反目标数组的数组边界。
由于在大多数机器上复制int型通常不会比复制char型慢,因此我认为这将使您的速度提高大约3倍。
扩展Doc Brown的答案,展开循环,这样你每读四次就写三个uint32_t
整数(uint64_t
将需要更大的大口,但会更难处理)。
如果您的pimg->m_data
和cvmColorImg.data
不在uint32_t
边界上开始,则读写int可能会出现问题。您可以通过在这些char*
数据成员之前放置int
或unsigned int
数据成员来强制实现这一点。或者你可以使用类似达夫的设备。个人偏好:我只会强制对齐。它使复制代码更干净、更容易,也许还更快。为填充而浪费的几个字节是一个很小的成本。
与展开循环的典型情况一样,您必须做一些特殊的事情来处理结束。(达夫的设备一开始就能处理奇怪的事情,所以这里不要用达夫的设备。)如果您填充输出缓冲区的末尾,使其占用4*N字节,那么循环结束处理的许多问题将会消失。
- gcc 如何优化此循环?
- 循环比较(优化)
- 为什么 std::chrono 在测量循环和编译器优化的并行 OpenMP 的执行时间时不起作用?
- 优化在网格图中查找哈密尔循环的函数?
- 未能优化看似明显的循环不变量(但volatile限定符发挥了神奇的作用)
- 在循环条件中调用const vector size()似乎缺少优化
- GCC 优化了基于固定范围的 for 循环,就好像它具有更长的可变长度一样
- 通过循环展开和阻塞进行优化
- 为什么 CLang++ 不优化循环,而 G++ 优化循环?
- 嵌套循环 C++ 的优化
- 如何在卷积程序的 c++ 中优化嵌套循环
- G 4.8.5带负数组索引的循环优化错误
- 使用 OpenMP 优化外循环并减少
- 编译时循环优化
- 有没有一种方法可以关闭C++和Rust编译中的循环优化
- c++循环优化和一些错误
- 用于顺序内存访问的编译器嵌套循环优化
- C++英特尔TBB内部循环优化
- c++ while循环优化不能正常工作
- "virtual"循环优化中的局部变量声明