遍历数组的简单任务.以下哪种解决方案最有效
The simple task of iterating through an array. Which of these solutions is the most efficient?
最近,我一直在思考可以遍历数组的所有方法,并想知道其中哪一种效率最高(和最低)。我写了一个假设的问题和五个可能的解决方案。
问题
给定一个int
数组arr
len
元素数量,为每个元素分配任意数量的42
的最有效方法是什么?
解决方案0:显而易见的
for (unsigned i = 0; i < len; ++i)
arr[i] = 42;
解决方案1:显而易见的反向
for (unsigned i = len - 1; i >= 0; --i)
arr[i] = 42;
解决方案 2:地址和迭代器
for (unsigned i = 0; i < len; ++i)
{ *arr = 42;
++arr;
}
解决方案3:反向地址和迭代器
for (unsigned i = len; i; --i)
{ *arr = 42;
++arr;
}
解决方案4:解决疯狂问题
int* end = arr + len;
for (; arr < end; ++arr)
*arr = 42;
㛆
几乎总是使用明显的解决方案,但我想知道下标运算符是否会导致乘法指令,就好像它写得像*(arr + i * sizeof(int)) = 42
一样.
反向解决方案试图利用i
与0
而不是len
进行比较如何减轻减法运算。因此,我更喜欢解决方案 3 而不是解决方案 2。此外,我读到数组经过优化,可以转发访问,因为它们在缓存中的存储方式,这可能会给解决方案 1 带来问题。
我不明白为什么解决方案 4 的效率会低于解决方案 2。解决方案 2 递增地址和迭代器,而解决方案 4 仅递增地址。
最后,我不确定我更喜欢哪种解决方案。我认为答案也因编译器的目标架构和优化设置而异。
如果有的话,您更喜欢其中哪一个?
只需使用 std::fill
.
std::fill(arr, arr + len, 42);
在您提出的解决方案中,在一个好的编译器上,两者都不应该比其他解决方案更快。
ISO标准没有规定代码中不同方式的效率(除了某些集合算法的某些大O类型的东西),它只是规定了它的功能。
除非你的数组有数十亿个元素的大小,或者你想每分钟设置它们数百万次,否则你使用哪种方法通常不会有丝毫区别。
如果你真的想知道(我仍然认为这几乎肯定是不必要的),你应该对目标环境中的各种方法进行基准测试。测量,不要猜测!
至于我更喜欢哪个,我的第一个倾向是优化可读性。只有当存在特定的性能问题时,我才会考虑其他可能性。那只是这样:
for (size_t idx = 0; idx < len; idx++)
arr[idx] = 42;
我不认为性能在这里是一个问题 - 如果有的话(我可以想象编译器为大多数生成相同的程序集),微优化几乎没有必要。
选择最具可读性的解决方案;标准库为您提供std::fill
,或用于更复杂的任务
for(unsigned k = 0; k < len; ++k)
{
// whatever
}
因此,对于查看您的代码的其他人来说,您在做什么是显而易见的。使用 C++11,您还可以
for(auto & elem : arr)
{
// whatever
}
只是不要试图在没有任何必要的情况下混淆你的代码。
对于几乎所有有意义的情况,编译器会将所有建议的情况优化为同一件事,并且不太可能产生任何差异。
曾经有一个技巧,如果你向后运行循环,你可以避免自动预取数据,这在某些奇怪的情况下实际上使它更有效率。我不记得确切的情况,但我希望现代处理器无论如何都会识别向后循环以及用于自动预取的前向循环。
如果应用程序对大量元素执行此操作非常重要,那么查看阻塞访问并使用非临时存储将是最有效的。但在执行此操作之前,请确保已将数组的填充确定为重要的性能点,然后对当前代码和改进的代码进行测量。
我可能会回来一些实际的基准来证明"它没有什么区别",但我有一项差事要跑,以免一天太晚......
- 运行同一解决方案的另一个项目的项目
- Project Euler问题4的错误解决方案
- 计算每个节点的树高,帮助我解释这个代码解决方案
- C++:Application.cpp中抛出了未解析的外部符号(解决方案在问题的末尾,供未来的读者参考)
- visual c++,如何获取解决方案目录中的代码
- 使用通常称为 API 实现C++多个客户和生产者解决方案,这是否有效?
- 哪些有效的解决方案可以检查Arraya是否包含Arrayb的所有元素
- 是否有一种记忆有效的方法来探索从输入排列产生的解决方案
- 当仅恒定项之一变化时,线性系统AX = B的有效解决方案
- 对于同一循环的这两个连续组,是否有更有效的解决方案
- 遍历数组的简单任务.以下哪种解决方案最有效
- 将一维矩阵数组转换为主一维矩阵的有趣算法挑战,需要有效的解决方案
- 找到解决方案的最有效方法-C++
- 神经网络图像分类,最有效的解决方案/建议
- 如何想出这样的解决方案?(检查数独是否有效)
- 创建并返回字符串向量——最有效的解决方案
- 欧拉#5项目;这个解决方案有效 - 但为什么
- 给定一个范围,我必须计算数组中数字的频率.给定的解决方案是否有效
- 有效测试多个学生的编程解决方案
- 使用可变模板(或其他解决方案)有效地对数据施加结构