c++优化简单循环
C++ optimize simple loop
我正在使用Visual Studio 2012并在x64发布模式上构建。下面的代码占用了我的程序运行所需时间的33.5%。我使用visual studio分析器来测量它。
//every variable is unsigned int or unsigned int*
for(unsigned int i = 0; i < num; i++)
{
unique[ids[i]]++;//2.1%
total[ids[i]] += main_list[id];//31.4%
}
有人可以推荐一种方法来减少这个函数需要运行的时间吗?
编辑:根据您的输入,我尝试了以下代码:
const unsigned int now = main_list[id];
for(unsigned int i = ids[0], j = 0; j < num; j++)
{
++unique[i];//2.0%
total[i] += now;//16.7%
i = ids[j];//16.8%
}
这证实了可能CPU分支预测失败的理论,因为位置是随机的(顺便说一句,它们不是完全随机的,而是排序的)。有什么办法可以加快我的代码吗?
第二次编辑:我尝试了以下内容:
const unsigned int now = main_list[id];
for(unsigned int i = ids[0], j = 0; j < num; j++)
{
total[i] += now;//2.0%
++unique[i];//16.7%
i = ids[j];//16.8%
}
您的代码没有得到任何本地友好性。我会提出两个可能的想法。
-
unique
和total
组在一起。struct Stuff { unsigned int unique, total; }; for(unsigned int i = 0; i < num; i++) { Stuff& s = stuffs[ids[i]]; s.unique++; s.total += main_list[id]; // <== is this supposed to be ids[i]? }
这将确保你在内存中连续访问的东西实际上在内存中彼此相邻。实际上,假设num
足够大,每一行都有缓存丢失。这就是你能得到的最糟糕的了。
-
排序
ids
。现在,你还在记忆里跳来跳去。让我们来确保我们可以按顺序执行:std::sort(ids, ids + num); // rest of loop as before
这样,很可能在处理stuffs[ids[i]]
时预取stuffs[ids[i+1]]
。
您可能会受到混叠的影响,因为它必须允许unique
, total
和main_list
在内存中重叠的可能性,从而阻止编译器在这里优化循环。
const auto mainListId = main_list[id];
for (unsigned int i = 0; i < num; ++i) {
const auto currId = ids[i];
++unique[currId];
total[currId] += mainListId;
}
当然,假设实际上没有任何混叠发生
对于这样一个简单的循环,你不能做更多的事情。您可以确保将编译器优化设置设置为最大值,如果编译器没有为您执行循环,您可以尝试展开循环。除此之外,您可能需要在这里展示的代码范围之外进行算法改进。
由于ids
的排序导致的非顺序内存访问,您可能存在内存绑定。这也许可以通过在此循环之前对ids
数组进行排序来解决,但如果没有更多的上下文来说明您正在尝试做的事情,很难说这是否有意义。
我对i = ids[j]; //16.8%
感到惊讶-这应该更快。看来时机不对了。++unique[i]; //2.0%
是一个非线性(不可预取)访问,应该更慢,而不是快8倍。事实上,ids[]
应该在缓存中,所以你只有八分之一的访问到达主存。语句应该比快8倍。你确定时机对,行动对吗?
也就是说,应该并行化循环。这不会有多大帮助;主存不会变快。但是你应该让主存储器忙起来。CPU预取器的思想是,如果没有显式访问,则抛出一些预测访问。如果预测是正确的,它节省了时间,否则它只是浪费了一点能量。
并行循环是可能的,因为ids[]
是排序的。即使存在重复值,它们也是相邻的,因此您可以通过查找重复值的第一次出现来找到分割点。
- 在c++中用vector填充一个简单的动态数组
- (C++)分析树以计算返回错误值的简单算术表达式
- 我的简单if-else语句是如何无法访问的代码
- 使用简单类型列表实现的指数编译时间.为什么
- 如何在BST的这个简单递归实现中消除警告
- 一种在C++中读取TXT配置文件的简单方法
- 关于简单C++函数(is_palindrome)的逻辑的问题
- 显示错误输出的简单数组排序程序
- 当无法使用模板和宏时,生成类型变体C++代码的最简单方法是什么?
- 退出简单while循环时出现问题
- 为什么简单的算术减法在"if"条件下不起作用?
- C++-字符串是否包含一个带有简单循环的单词
- 关于 c++ 函数中指针赋值的简单问题
- 从函数返回任意简单类型的数据
- 如何在没有函数的情况下编写此代码并使C++更简单?
- 有没有办法简单地从 GPU 调用多个 cpp 输出文件?
- 在简单示例中,Python3 + ctypes 回调会导致内存泄漏
- 当简单捕获中的标识符显示为参数的声明符 ID 时,没有编译器诊断
- 如何使用 samtools C API 构建一个简单的主.cpp文件
- CPU 瓶颈;处理具有许多非静态对象的 3D 场景渲染的简单方法