【发布时间】:2011-05-10 15:36:16
【问题描述】:
我正在做一个家庭作业,我必须手动优化嵌套循环(我的程序将在禁用优化的情况下编译)。作业的目标是在 6 秒内运行整个程序(额外得分少于 4.5 秒)。
我只允许修改一小段代码,起点是这样的:
for (j=0; j < ARRAY_SIZE; j++) {
sum += array[j];
}
其中ARRAY_SIZE 是 9973。此循环包含在另一个循环中,该循环运行了 200,000 次。这个特定版本在 16 秒内运行。
到目前为止,我所做的是更改实现以展开循环并使用指针作为我的迭代器:
(这些声明不会循环超过 200,000 次)
register int unroll_length = 16;
register int *unroll_end = array + (ARRAY_SIZE - (ARRAY_SIZE % unroll_length));
register int *end = array + (ARRAY_SIZE -1);
register int *curr_end;
curr_end = end;
while (unroll_end != curr_end) {
sum += *curr_end;
curr_end--;
}
do {
sum += *curr_end + *(curr_end-1) + *(curr_end-2) + *(curr_end-3) +
*(curr_end-4) + *(curr_end-5) + *(curr_end-6) + *(curr_end-7) +
*(curr_end-8) + *(curr_end-9) + *(curr_end-10) + *(curr_end-11) +
*(curr_end-12) + *(curr_end-13) + *(curr_end-14) + *(curr_end-15);
}
while ((curr_end -= unroll_length) != array);
sum += *curr_end;
使用这些技术,我能够将执行时间缩短到 5.5 秒,这将是我的功劳。然而;我确实想获得额外的积分,但我也很好奇我可以做哪些额外的优化而我可能会忽略?
编辑#1(添加外循环)
srand(time(NULL));
for(j = 0; j < ARRAY_SIZE; j++) {
x = rand() / (int)(((unsigned)RAND_MAX + 1) / 14);
array[j] = x;
checksum += x;
}
for (i = 0; i < N_TIMES; i++) {
// inner loop goes here
if (sum != checksum)
printf("Checksum error!\n");
sum = 0;
}
【问题讨论】:
-
被求和的数组每次都会改变吗?看看外循环也会很有帮助。
-
数组没有变化。我已将外部循环添加到问题中。
-
按 4 或 8 步进行。尝试查看分项是否有帮助。查看生成的程序集,调试版本确实喜欢将值写回堆栈,只是为了提供更好的调试器反馈。
-
预计算你可以的东西:(ARRAY_SIZE - (ARRAY_SIZE % 10)),取模可能很昂贵。
-
……当然,Duff’s device 对于展开内部循环很有用。
标签: c optimization