假设我有一个向量:
vector<int> v;
Run Code Online (Sandbox Code Playgroud)
我希望它填充 0 到 9 的整数。那么我这里有几个选项:
v.resize(10);
for (int i = 0; i < 10; i++) {
v[i] = i;
}
// or
v.reserve(10);
for (int i = 0; i < 10; i++) {
v.push_back(i);
}
// or
iota(v.begin(), v.end(), 0);
Run Code Online (Sandbox Code Playgroud)
与其他两种方法相比,使用 std::iota 是否有任何内存/时间优势?我个人认为前两者更具可读性,尽管我可能会将其与平易近人性混为一谈,因为我无论如何都不是 C++ 专家。
小智 0
该任务有很多潜在的解决方案。
但。push_back和其他方法之间存在差异。push_back需要一个空的std::vector,而其他人则处理std::vector具有给定大小的 a 。
此外。对于 10 个元素,执行时间的增量很小。调用开销可能需要比迭代std::vector和赋值更多的时间。
因此,为了获得某种可靠的比较,我们应该更长时间、更频繁地运行循环。
预期这push_back是最慢的函数,因为内部检查是否有足够的空间。
基于范围的for循环、基于 和 do 的循环iterators都std::generate遵循std::iota相同的基本机制。迭代和赋值。他们还需要一个额外的变量。
多线程可能会有所帮助,但这取决于您的系统
最快的应该是“正常”循环。由于它的占地面积最小,我建议使用它。
但是,您需要检查您的系统。
请看下面的示例代码:
#include <iostream>
#include <vector>
#include <numeric>
#include <chrono>
#include <algorithm>
#include <future>
#include <array>
struct Timer {
std::chrono::time_point<std::chrono::high_resolution_clock> startTime{};
long long elapsedTime{};
void start() { startTime = std::chrono::high_resolution_clock::now(); }
void stop() { elapsedTime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - startTime).count(); }
friend std::ostream& operator << (std::ostream& os, const Timer& t) { return os << t.elapsedTime << " ms "; }
};
constexpr std::size_t MaxSize = 50'000'000ull;
static constexpr std::size_t NumberOfThreads = 4;
static constexpr std::size_t BlockSize = 25;
static constexpr std::size_t MaxRepetition = NumberOfThreads * BlockSize;
int fillVector(std::vector<std::size_t>& v) {
for (std::size_t k{}; k < BlockSize; ++k)
for (std::size_t i{}; i < MaxSize; ++i)
v[i] = i;
return 0;
}
int main() {
Timer t{};
{
std::vector<std::size_t> v{};
v.reserve(MaxSize);
t.start();
for (std::size_t r{}; r < MaxRepetition; ++r) {
for (std::size_t i{}; i < MaxSize; ++i)
v.push_back(i);
v.clear();
}
t.stop(); std::cout << "push_back:\t\t " << t << '\n';
}
{
std::vector<std::size_t> v(MaxSize);
t.start();
for (std::size_t r{}; r < MaxRepetition; ++r)
for (std::size_t i{}; i < MaxSize; ++i)
v[i] = i;
t.stop(); std::cout << "Standard loop:\t\t " << t << '\n';
t.start();
for (std::size_t r{}; r < MaxRepetition; ++r)
for (std::size_t i{}; std::size_t & vi : v) vi = i++;
t.stop(); std::cout << "range based for loop:\t " << t << '\n';
std::size_t k{};
t.start();
for (std::size_t r{}; r < MaxRepetition; ++r) {
k = 0;
for (auto i = v.begin(); i != v.end(); ++i)
*i = k++;
}
t.stop(); std::cout << "with iterators:\t\t " << t << '\n';
t.start();
for (std::size_t r{}; r < MaxRepetition; ++r)
std::generate(v.begin(), v.end(), [i = 0ull]() mutable { return i++; });
t.stop(); std::cout << "std::generate:\t\t " << t << '\n';
t.start();
for (std::size_t r{}; r < MaxRepetition; ++r)
std::iota(v.begin(), v.end(), 0);
t.stop(); std::cout << "std::iota: \t\t " << t << '\n';
t.start();
std::array<std::shared_future<int>, NumberOfThreads> dummy{};
for (std::size_t threadNumber{}; threadNumber < NumberOfThreads; ++threadNumber) {
dummy[threadNumber] = std::async(fillVector, std::ref(v));
}
for (unsigned int threadNumber{}; threadNumber < NumberOfThreads; ++threadNumber) {
dummy[threadNumber].wait();
}
t.stop(); std::cout << "std::async: \t\t " << t << '\n';
}
}
Run Code Online (Sandbox Code Playgroud)
这会在我的 2012 年 Windows 7 计算机上产生以下输出
push_back: 8805 ms
Standard loop: 1441 ms
range based for loop: 3394 ms
with iterators: 3397 ms
std::generate: 3409 ms
std::iota: 3402 ms
std::async: 1499 ms
Run Code Online (Sandbox Code Playgroud)
对于如此小的函数来说,多线程可能没有多大意义。
使用计时功能进行的时间测量也可能不如预期准确。
| 归档时间: |
|
| 查看次数: |
1249 次 |
| 最近记录: |