gpt4 book ai didi

c++ - 为什么添加两个值在运行时有如此高的可变性?

转载 作者:太空狗 更新时间:2023-10-29 23:38:38 31 4
gpt4 key购买 nike

我编写了一个计时函数,用于记录函数的运行时间并计算多次运行的平均值和标准差。我很惊讶地发现标准偏差非常高,即使是看似简单的任务,例如添加两个 double 。我用 python 分析了数据(见图表)。 C++ 输出为 19.6171 ns +/- 21.9653ns (82799807 runs)编译时:

gcc version 8.3.0 (Debian 8.3.0-19)
/usr/bin/c++ -O3 -DNDEBUG -std=gnu++17

整个测试是在我的个人电脑上完成的,我的电脑并没有空闲,而是运行着一个DE、一个浏览器、我的IDE和其他进程。虽然在测试期间有可用的 RAM。我的 HT 双核 CPU 闲置使用率低于 10%。
对于这种情况,是否会出现从 20 ns 到 50 µs 的平均值的尖峰?

运行时间图
这是std::vector<double> run_times的内容.我没有看到任何模式。 Plot of runtimes over

运行时间直方图
注意 log y 轴(此 bin 中的样本数)。 Histogram of run times

时间.h

#include <cstdint>
#include <ostream>
#include <cmath>
#include <algorithm>
#include <vector>
#include <chrono>
#include <numeric>
#include <fstream>


struct TimingResults{
// all time results are in nanoseconds
double mean;
double standard_deviation;
uint64_t number_of_runs;
};


std::ostream& operator<<(std::ostream& os, const TimingResults& results);


template <typename InputIterator>
std::pair<typename InputIterator::value_type, typename InputIterator::value_type>
calculate_mean_and_standard_deviation(InputIterator first, InputIterator last){
double mean = std::accumulate(first, last, 0.) / std::distance(first, last);
double sum = 0;
std::for_each(first, last, [&](double x){sum += (x - mean) * (x - mean);});
return {mean, std::sqrt(sum / (std::distance(first, last) - 1))};
}


template<uint64_t RunTimeMilliSeconds = 4000, typename F, typename... Args>
TimingResults measure_runtime(F func, Args&&... args){
std::vector<double> runtimes;
std::chrono::system_clock::time_point b;
auto start_time = std::chrono::high_resolution_clock::now();
do {
auto a = std::chrono::high_resolution_clock::now();
func(std::forward<Args>(args)...);
b = std::chrono::high_resolution_clock::now();
runtimes.push_back(std::chrono::duration_cast<std::chrono::nanoseconds>(b - a).count());
} while (std::chrono::duration_cast<std::chrono::milliseconds>(b-start_time).count() <= RunTimeMilliSeconds);
auto [mean, std_deviation] = calculate_mean_and_standard_deviation(runtimes.begin(), runtimes.end());
return {mean, std_deviation, runtimes.size()};
}

定时.cpp

#include <iostream>
#include "timing.h"


std::ostream& operator<<(std::ostream& os, const TimingResults& results){
return os << results.mean << " ns" << " +/- " << results.standard_deviation << "ns ("
<< results.number_of_runs << " runs)";
}

main.cpp

#include "src/timing/timing.h"
#include <iostream>


int main(){
auto res = measure_runtime([](double x, double y){return x * y;}, 6.9, 9.6);
std::cout << res;
}

最佳答案

现代 CPU 很容易以几个 10^9 FLOPS 的数量级执行,即一次操作的预期时间低于 1 ns。然而,这是指峰值性能。对于大多数现实世界的工作负载,由于内存和缓存效应,性能会低得多。

您的基准测试的问题是您在为个别操作计时。获取时间点 ab 的开销可能只是超出了您实际尝试测量的时间。此外,即使 std::chrono::high_resolution_clock 也不会给你皮秒精度(尽管这在原则上取决于实现和硬件)。显而易见的解决方法是执行操作 N 次,然后将总时间除以 N。在某些时候,您会发现您的结果变得一致。 (请随意发布您的结果。)

TL;DR:您正在尝试用怀表为闪电计时。

关于c++ - 为什么添加两个值在运行时有如此高的可变性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57691672/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com