【发布时间】:2011-11-18 19:17:39
【问题描述】:
我有一个消耗 cpu 的代码,其中一些带有循环的函数被执行 很多 次。此循环中的每个优化都会带来显着的性能提升。问题:你会如何优化这个循环(虽然没有更多的优化......)?
void theloop(int64_t in[], int64_t out[], size_t N)
{
for(uint32_t i = 0; i < N; i++) {
int64_t v = in[i];
max += v;
if (v > max) max = v;
out[i] = max;
}
}
我尝试了一些东西,例如我用在每个循环中递增的指针替换了数组,但是(令人惊讶的是)我失去了一些性能而不是获得...
编辑:
- 更改了一个变量的名称(
itsMaximums,错误) - 函数是类的方法
- in 和 put 是
int64_t,所以是负数和正数 - `(v > max) 可以评估为真:考虑实际最大值为负时的情况
- 代码在 32 位电脑(开发)和 64 位(生产)上运行
-
N在编译时未知 - 我尝试了一些 SIMD,但未能提高性能...(将变量移动到
_m128i,执行和存储回的开销高于 SSE 速度增益。但我不是 SSE 专家,所以也许我的代码很糟糕)
结果:
我添加了一些循环展开,和来自 Alex 的帖子的一个不错的 hack。下面我贴一些结果:
- 原文:14.0s
- 展开循环(4 次迭代):10.44 秒
- Alex 的技巧:10.89 秒
- 2) 和 3) 一次:11.71 秒
stage,即 4) 并不比 3) 和 4) 快。下面是 4) 的代码:
for(size_t i = 1; i < N; i+=CHUNK) {
int64_t t_in0 = in[i+0];
int64_t t_in1 = in[i+1];
int64_t t_in2 = in[i+2];
int64_t t_in3 = in[i+3];
max &= -max >> 63;
max += t_in0;
out[i+0] = max;
max &= -max >> 63;
max += t_in1;
out[i+1] = max;
max &= -max >> 63;
max += t_in2;
out[i+2] = max;
max &= -max >> 63;
max += t_in3;
out[i+3] = max;
}
【问题讨论】:
-
这是您的实际代码吗? itsMaximums 是一个全局变量吗? in数组中的数字是正数还是负数?
-
它的最大值在哪里定义?
-
与性能无关,但为什么 N 是 size_t 而 i 是 uint32_t?
-
@JakubM.:获得一台 64 位机器进行测试。如果您在完全不同的指令集上进行测试,而不是在生产中使用,那么执行此类低级优化是没有意义的。当针对 64 位机器时,生成的代码会完全不同,这就是您应该尝试优化的地方
-
@JakubM。 6502 刚刚在聊天中提到,使用 CUDA 有一种模式(称为 scan)可以有效地执行类似于您的操作。请参阅developer.nvidia.com/cuda-cc-sdk-code-samples#scan - 如果您仍有进一步优化的目标,我认为您可能会感兴趣 (more background)
标签: c++ performance optimization g++