【发布时间】:2011-11-03 21:35:13
【问题描述】:
在对之前关于将 RGB 转换为 RGBA 和 ARGB 转换为 BGR 的一些问题的后续行动中,我想通过 SSE 加快 RGB 到 BGRA 的转换.假设一台 32 位机器,并且想使用 intrinsics。我很难将源缓冲区和目标缓冲区对齐以使用 128 位寄存器,并寻求其他精明的矢量化解决方案。
要向量化的套路如下...
void RGB8ToBGRX8(int w, const void *in, void *out)
{
int i;
int width = w;
const unsigned char *src= (const unsigned char*) in;
unsigned int *dst= (unsigned int*) out;
unsigned int invalue, outvalue;
for (i=0; i<width; i++, src+=3, dst++)
{
invalue = src[0];
outvalue = (invalue<<16);
invalue = src[1];
outvalue |= (invalue<<8);
invalue = src[2];
outvalue |= (invalue);
*dst = outvalue | 0xff000000;
}
}
此例程主要用于大型纹理 (512KB),因此如果我可以并行化一些操作,一次处理更多像素可能会有所帮助。当然,我需要配置文件。 :)
编辑:
我的编译参数...
gcc -O2 main.c
【问题讨论】:
-
您是否在为您的编译器使用优化标志(哪个?)?编译器通常会更好地优化代码,不会引入错误。您收集了哪些基准数据?
-
不是 SSE 答案,但您是否尝试过展开循环 4 次以使输入始终从对齐的地址开始?然后,您可以一次读取输入一个机器字,而不是按字节读取,并对源像素的每个相对位置进行专门的移位和屏蔽。正如 Dana 所提到的,值得看看编译器在高优化级别上的表现如何(检查生成的汇编代码,除了基准测试),但我怀疑它是否会足够积极地展开循环和根据
in的对齐方式全部自行拆分入口点。 -
好问题。它只是 GCC4.6 的“O2”(不是 O3)。我的基准案例是 10K 迭代运行,512 作为“宽度”跨度。感谢您的精彩回复!
标签: c opengl sse simd vectorization