我有一个32位RGBA图像缓冲区。我们假设它是,例如1920x1080 - 典型的从左到右,从上到下的RAW缓冲区。
这是我想要快速做的事情:从这个源缓冲区创建两个新的缓冲区......
对于输入缓冲区的每个像素,我的(慢)解决方案如下:
u_int32_t pixel = *srcPtr++; // grab the source 32-bit pixel value
*fillPtr++ = pixel | 0xff; // FILL: keep only the RGB channels (alpha = 0xff)
pixel &= 0xff; // KEY: grab just the alpha value
*keyPtr++ = (pixel<<24) | (pixel<<16) | (pixel<<8) | 0xff; // KEY: xfer alpha to RGB, alpha = 0xff
可以假设源缓冲区是16字节对齐的。
一些初步测试在1920x1080图像上的时钟大约为8ms - Intel Xeon E5,hex-core,12MB L3缓存,3.5Ghz。
有人可以提供他们的SSE3教学专业知识来提高一些加速度吗?
答案 0 :(得分:2)
听起来这是你想要的基础 - 它一次处理四个像素。
void split_pixels(__m128i src, __m128i *fill, __m128i *key)
{
__m128i const alphamask = _mm_set_epi8(-1, 0, 0, 0, -1, 0, 0, 0,
-1, 0, 0, 0, -1, 0, 0, 0);
__m128i const fillmask = _mm_set_epi8(-1, 15, 15, 15, -1, 12, 12, 12,
-1, 7, 7, 7, -1, 3, 3, 3);
_mm_stream_si128(fill, _mm_or_si128(src, alphamask));
_mm_stream_si128(key, _mm_or_si128(_mm_shuffle_epi8(src, fillmask), alphamask));
}
它使用SSE shuffle指令,它通过寄存器中的索引对字节进行混洗。它还使用流媒体存储,因为您无法在缓存中容纳三个1080p缓冲区。流媒体商店很挑剔,可能会或可能没有帮助,这取决于你正在做什么,所以我会对那些进行基准测试。
请注意,此问题是内存带宽的高度瓶颈,因此虽然它可能比普通的C版本运行得更快,但它的运行速度可能会快4倍。您可以在商店之前捆绑的处理越多,它的执行速度就越快。
答案 1 :(得分:0)
除了Cory的回答,您还可以尝试多个线程。即使这是使用多个线程can increase the throughput for a single socket system by up to a factor of two进行内存绑定(在多插槽系统上甚至更多)。
您可以使用OpenMP
执行此类操作#pragma omp parallel for
for(int i=0; i<height; i++) {
for(int j=0; <width; j+=4) {
split_pixels(&src[i*width+j], &fill[i*width+j], &key[i*width+j])
}
}