【发布时间】:2014-11-26 15:46:18
【问题描述】:
我正在尝试优化屏蔽数组的算法。初始代码如下所示:
void mask(unsigned int size_x, unsigned int size_y, uint32_t *source, uint32_t *m)
{
unsigned int rep=size_x*size_y;
while (rep--)
{
*(source++) &= *(m++);
}
}
我尝试过循环展开+预取
void mask_LU4(unsigned int size_x, unsigned int size_y, uint32_t *source, uint32_t *mask)
{ // in place
unsigned int rep;
rep= size_x* size_y;
rep/= 4 ;
while (rep--)
{
_mm_prefetch(&source[16], _MM_HINT_T0);
_mm_prefetch(&mask[16], _MM_HINT_T0);
source[0] &= mask[0];
source[1] &= mask[1];
source[2] &= mask[2];
source[3] &= mask[3];
source += 4;
mask += 4;
}
}
并使用内在函数
void fmask_SIMD(unsigned int size_x, unsigned int size_y, uint32_t *source, uint32_t *mask)
{ // in place
unsigned int rep;
__m128i *s,*m ;
s = (__m128i *) source;
m = (__m128i *) mask;
rep= size_x* size_y;
rep/= 4 ;
while (rep--)
{
*s = _mm_and_si128(*s,*m);
source+=4;mask+=4;
s = (__m128i *) source;
m = (__m128i *) mask;
}
}
但是性能是一样的。我尝试对 SIMD 和 Loop Unrolling 版本执行 sw 预取,但我看不到任何改进。关于如何优化此算法的任何想法?
P.S.1:我使用的是 gcc 4.8.1,并使用 -march=native 和 -Ofast 进行编译。
P.S.2:我使用的是 Intel Core i5 3470 @3.2Ghz,Ivy 桥架构。 L1 DCache 4X32KB(8 路),L2 4x256,L3 6MB,RAM-DDR3 4Gb(双通道,DRAM @798,1Mhz)
【问题讨论】:
-
我怀疑数组足够大,以至于您实际上是在测量内存带宽。对此你无能为力,除了“不做”。
-
新 CPU 不会自动预加载吗?
-
@Jake'Alquimista'LEE 现在连老家伙都可以了
-
@harold 是正确的。这是内存带宽限制。而且由于源和目标是相同的流指令将无济于事。但是你可以使用多个线程。与许多人认为单线程不会使主内存带宽饱和的情况相反。
-
在使用内部函数等之前,您是否检查了生成的代码?它很可能已经被矢量化了。
标签: gcc optimization x86 simd bitmask