int *s;
allocate memory for s[100];
void func (int *a, int *b)
{
int i;
for (i = 0; i < 100; i++)
{
s[i] = a[i] ^ b[i];
}
}
Run Code Online (Sandbox Code Playgroud)
假设这个特定的代码片段被调用了1000次,这是我代码中最耗时的操作.还假设每次更改a和b的地址.'s'是一个全局变量,使用a和b的不同值集更新.
据我所知,主要的性能瓶颈是内存访问,因为唯一的其他操作是XOR,这非常简单.
您能否建议我如何以最佳方式优化我的代码?
我真的想问的问题,但我认为没有得到恰当的传达,例如,这个for循环包含10个这样的XOR操作,循环计数为100,函数调用1000次,点是高内存如果代码要在单个核心机器上执行,那么改进的范围是什么?
我已经测试了提出的解决方案,以及其他两个.由于保存到s []的结果不正确,我无法测试onemasse的提议.我也无法修复它.我不得不对moonshadow代码做一些改变.测量单位是时钟周期,因此越低越好.
原始代码:
#define MAX 100
void inline STACKO ( struct timespec *ts, struct timespec *te ){
int i, *s, *a, *b;
for (i = 0; i < MAX; ++i){
s = (int *) malloc (sizeof (int)); ++s;
a = (int *) malloc (sizeof (int)); ++a;
b = (int *) malloc (sizeof (int)); ++b;
}
srand ( 1024 );
for (i = 0; i < MAX; ++i){
a[i] = ( rand() % 2 );
b[i] = ( rand() % 2 );
}
rdtscb_getticks ( ts ); /* start measurement */
for (i = 0; i < MAX; i++)
s[i] = a[i] ^ b[i];
rdtscb_getticks ( te ); /* end measurement */
/*
printf("\n");
for (i = 0; i < MAX; ++i)
printf("%d", s[i]);
printf("\n");
*/
}
Run Code Online (Sandbox Code Playgroud)
新提案1:注册int
从:
int i, *s, *a, *b;
Run Code Online (Sandbox Code Playgroud)
至:
register int i, *s, *a, *b;
Run Code Online (Sandbox Code Playgroud)
新提案2:没有数组表示法
s_end = &s[MAX];
for (s_ptr = &s[0], a_ptr = &a[0], b_ptr = &b[0]; \
s_ptr < s_end; \
++s_ptr, ++a_ptr, ++b_ptr){
*s_ptr = *a_ptr ^ *b_ptr;
}
Run Code Online (Sandbox Code Playgroud)
moonshadow建议优化:
s_ptr = &s[0];
a_ptr = &a[0];
b_ptr = &b[0];
for (i = 0; i < (MAX/4); i++){
s_ptr[0] = a_ptr[0] ^ b_ptr[0];
s_ptr[1] = a_ptr[1] ^ b_ptr[1];
s_ptr[2] = a_ptr[2] ^ b_ptr[2];
s_ptr[3] = a_ptr[3] ^ b_ptr[3];
s_ptr+=4; a_ptr+=4; b_ptr+=4;
}
Run Code Online (Sandbox Code Playgroud)
moonshadow提出优化+寄存器int:
从:
int i, *s, ...
Run Code Online (Sandbox Code Playgroud)
至:
register int i, *s, ...
Run Code Online (Sandbox Code Playgroud)
Christoffer提议优化:
#pragma omp for
for (i = 0; i < MAX; i++)
{
s[i] = a[i] ^ b[i];
}
Run Code Online (Sandbox Code Playgroud)

Original Code 1036.727264
New Proposal 1 611.147928
New proposal 2 450.788845
moonshadow 713.3845
moonshadow2 452.481192
Christoffer 1054.321943
Run Code Online (Sandbox Code Playgroud)
还有其他简单的方法可以优化生成的二进制文件.将-O2传递给gcc告诉您需要优化.要确切了解-O2的作用,请参阅gcc手册页.
启用-O2后:

Original Code 464.233031
New Proposal 1 452.620255
New proposal 2 454.519383
moonshadow 428.651083
moonshadow2 419.317444
Christoffer 452.079057
Run Code Online (Sandbox Code Playgroud)
源代码见:http://goo.gl/ud52m
不要使用循环变量来索引.展开循环.
for (i = 0; i < (100/4); i++)
{
s[0] = a[0] ^ b[0];
s[1] = a[1] ^ b[1];
s[2] = a[2] ^ b[2];
s[3] = a[3] ^ b[3];
s+=4; a+=4; b+=4;
}
Run Code Online (Sandbox Code Playgroud)
了解如何在您的平台上执行SIMD XOR.
将这些XOR作为显式步骤执行可能比作为另一个计算的一部分执行更昂贵:您必须从a和b读取并将结果存储在s中 - 如果再次读取s以进行更多计算,则可以节省每次迭代读取和写入,以及所有函数调用和循环开销,通过在那里进行异或; 同样,如果a和b是某些其他函数的输出,则可以通过在其中一个函数的末尾执行XOR来做得更好.