我对低级内存优化知之甚少,但我试图弄清楚如何从保存rbg32数据的unsigned char数组优化内存访问。
我正在构建一个需要平均数据区域的directshow变换滤镜(CTransInPlaceFilter)。提供给我的数据是rgb32格式(B G R 0xFF B G R 0xFF B G R 0xFF etc
)。我正在循环数据并计算平均红色,绿色和蓝色通道。
我发现当我取消引用字节数组中的数据时,视频播放运行CPU并且没有和访问,CPU没有那么多工作。
在阅读了大量帖子后,我认为这是CPU带宽瓶颈的记忆。
以下是转换函数的代码:
HRESULT CFilter :: Transform(IMediaSample * pSample){
BYTE* data = NULL; pSample->GetPointer(&data); if (mVideoType == MEDIASUBTYPE_RGB32) { Rect roi(0, 0, 400, 400); // Normally this is dynamic int totalPixels = roi.width * roi.height; // Find the average color unsigned int totalR = 0, totalG = 0, totalB = 0; for (int r = 0; r < roi.height; r++) { int y = roi.y + r; BYTE* pixel = data + (roi.x + y * mWidth) * 4; // 4 bytes per pixel for (int c = 0; c < roi.width; c++) { totalB += *pixel; // THESE 3 LINES IS THE ISSUE totalG += *(++pixel); totalR += *(++pixel); pixel++; } } int meanR = (int)floor(totalR / totalPixels); int meanG = (int)floor(totalG / totalPixels); int meanB = (int)floor(totalB / totalPixels); // Does work with the averaged data } return S_OK; }
因此,当我在没有3个解除引用线的情况下运行视频时,我获得了大约10-14%的cpu使用率。通过这些线路,我可以获得30-34%的CPU使用率。
我还尝试将数据复制到缓冲区以访问数据。
mempy(mData, data, mWidth * mHeight * 4); // mData is only allocated once in constructor
...
totalB += mData[x + y * mWidth];
cpu使用率变为22-25%。
是否可以将CPU使用率再次降低到接近10?以某种方式更快地访问数据?我应该尝试使用asm吗?
其他信息:视频为10bit 1280 X 720,使用GraphEdit测试我的过滤器。 我的过滤器不会更改源图像(因此它不会复制)。 如果有帮助,我可以解决这个过程。
提前致谢!
修改
有关详细信息,我添加了directshow图表。视频是10位,但Lav滤镜将RGB32(8位)传递给我。它是调试版本,会释放它的速度(最终我将编译为发布版本)。
我运行了两种不同的方式(前面提到过)并对它们的经过时间进行了基准测试。通过解除引用,每次转换运行时我会得到0.126208毫秒。如果没有解除引用,我会得到0.009毫秒。
我还尝试通过
来减少循环for (int c = 0; c < roi.width; c += 4) {
totalB += pixel[c] + pixel[c + 3] + pixel[c + 6] + pixel[c + 9];
totalG += pixel[c + 1] + pixel[c + 4] + pixel[c + 7] + pixel[c + 10];
totalR += pixel[c + 2] + pixel[c + 5] + pixel[c + 8] + pixel[c + 11];
}
这没有改变CPU使用率,经过的时间仍然在0.12左右
编辑2:
我还在发布中构建了所有依赖项和项目本身,并得到了相同的结果。访问速度仍然很慢。
答案 0 :(得分:1)
我解决了这个问题。所以问题是数据是指向视频内存中数据的指针。我试图使用数据并将其从视频传输到计算机RAM,从而导致内存带宽错误。立即复制所有数据(memcpy)更快但仍然很慢。相反,我必须使用特定的英特尔SSE4命令有效地将数据从视频内存复制到计算机内存。
我使用了this file(gpu_memcpy)。它包含与memcpy类似的功能,但使用GPU来完成工作。它速度更快,复制后,访问数据的速度很快。