为什么for循环中的异步不能提高执行时间

Why does async in a for loop not improve execution time?

本文关键字:不能 执行时间 异步 for 循环 为什么      更新时间:2023-10-16

我正在努力了解并发性,所以我试图从《C++教程》(第二版(15.7.3第205页中编写一个更灵活的版本(my_comp(((的Stroustrup示例代码(comp4(((。它给出了正确的答案,但没有使用并发来提高执行时间。我的问题是:为什么My_comp((没有按预期运行,我该如何修复它?

#include <iostream>
#include <chrono>
#include <cmath>
#include <vector>
#include <numeric>
#include <future>
#include <fstream>
using namespace std;
using namespace std::chrono;
constexpr auto sz = 500'000'000;
constexpr int conc_num{ 4 };
double accum(double* beg, double* end, double init)
{
return accumulate(beg, end, init);
}
double comp4(vector<double>& v)
//From Stroustrup, A Tour of C++ (Second edition)
//15.7.3 page 205
{
auto v0 = &v[0];
auto sz = v.size();
auto f0 = async(accum, v0, v0 + sz / 4, 0.0);
auto f1 = async(accum, v0 + sz / 4, v0 + sz / 2, 0.0);
auto f2 = async(accum, v0 + sz / 2, v0 + sz * 3 / 4, 0.0);
auto f3 = async(accum, v0 + sz * 3 / 4, v0 + sz, 0.0);
return f0.get() + f1.get() + f2.get() + f3.get();
}
double my_comp(vector<double>& v, int conc = 1)
//My idea of a more flexible version of comp4
{
if (conc < 1)
conc = 1;
auto v0 = &v[0];
auto sz = v.size();
vector<future<double>> fv(conc);
for (int i = 0; i != conc; ++i) {
auto f = async(accum, v0 + sz * (i / conc), v0 + sz * ((i + 1) / (conc)), 0.0);
fv[i] = move(f);
}
double ret{ 0.0 };
for (int i = 0; i != fv.size(); ++i) {
ret += fv[i].get();
}
return ret;
}
int main()
{
cout << "Calculating ..." << "nn";
auto tv0 = high_resolution_clock::now();
vector<double> vc;
vc.reserve(sz);
for (int i = 0; i != sz; ++i) {
vc.push_back(sin(i));   //Arbitrary test function
}
auto tv1 = high_resolution_clock::now();
auto durtv = duration_cast<milliseconds>(tv1 - tv0).count();
cout << "vector of size " << vc.size() << ":  " << durtv << " msecnn";
////////////////////////////////////////////
auto vc_test = vc;
auto t0 = high_resolution_clock::now();
auto s1 = accumulate(vc_test.begin(), vc_test.end(), 0.0);
auto t1 = high_resolution_clock::now();
auto dur1 = duration_cast<milliseconds>(t1 - t0).count();
///////////////////////////////////////////
vc_test = vc;
auto tt0 = high_resolution_clock::now();
auto s2 = my_comp(vc_test, conc_num);       //Should be faster
auto tt1 = high_resolution_clock::now();
auto dur2 = duration_cast<milliseconds>(tt1 - tt0).count();
////////////////////////////////////////////
vc_test = vc;
auto ttt0 = high_resolution_clock::now();
auto s3 = comp4(vc_test);       //Really is faster
auto ttt1 = high_resolution_clock::now();
auto dur3 = duration_cast<milliseconds>(ttt1 - ttt0).count();
///////////////////////////////////////////
cout << dur1 << " msecn";
cout << "Output = " << s1 << " (accumulate)" << "nn";
cout << dur2 << " msec" << "  Ratio:  " << double(dur2) / double(dur1) << "n";
cout << "Output = " << s2 << " (my_comp)" << "nn";
cout << dur3 << " msec" << "  Ratio:  " << double(dur3) / double(dur1) << "n";
cout << "Output = " << s3 << " (comp4)" << "nn";
}

使用Visual C++2019(ISO C++17 Standard(/std:C++17((X64版本编译。典型的输出是:

424毫秒输出=1.93496(累加(

431毫秒比率:1.01651输出=1.93496(my_comp(

117毫秒比率:0.275943输出=1.93496(comp4(

我知道并行算法和std::reduce。我的问题不是如何优化这个特定的计算,而是学习如何编写符合预期的并发代码。

您的问题在这里:(i / conc)。一旦0 <= i < conciconc是整数,这意味着该计算总是零。

要解决您的问题,请删除括号:

auto f = async(accum, v0 + sz * i / conc, v0 + sz * (i + 1) / conc, 0.0);