多个调用异步,用于C++中的更新向量或列表

Multiple Call Async for update vector or list in C++

本文关键字:更新 向量 列表 C++ 调用 异步 用于      更新时间:2023-10-16

我陷入了多个这样的异步问题 例:

void updateList(vector<int> &list, int value){
list.push_back(value);
}
int main(){
vector<future<void>> asyncTasks;
vector<int> list;
for(int i = 0; i < 10; i ++){
asyncTasks.push_back(async(launch::async, updateList,i ));
}
for(auto &&f : asyncTasks){
f.get();
}
}

问题是有时它会抛出有关插入暴力的错误。

你能给我任何想法吗?

问题是你在updateList中同时做两件事:

  1. 根据给定的指数计算值(计算是指仅使用它(
  2. 向容器添加值

并行执行第二个没有多大意义,因为您必须在容器上进行序列化,否则会出现数据争用,这就是错误的原因。

void updateList(vector<int> &list, int value){
list.push_back(value); //< Data race-> Undefined behavior -> Sometimes Crash 
}

但是我们可以做一些可以轻松并行的事情,即 1. 计算一个值。 如果我们只是在容器中添加虚拟零,首先,我们可以修改容器中的元素,即std::vector,因为我们不修改容器本身,如计数或排序,只修改它的成员。

因此,在那之后,您可以并行计算,但为什么不直接使用新的并行算法为我们执行此操作呢?所以我添加了第二个解决方案。

此外,你的工作由无法平行的工作和可以平行的工作组成的发现,可以在阿姆达尔定律中找到。

#include <iostream>
#include <vector>
#include <numeric>
#include <algorithm>
#include <execution>
#include <future>

//Your modified solution
void updateList(std::vector<int> &list, int value){
const auto index = value;
//Do the heavy stuff here
list[index]  = value;
}
int main(){
std::vector<int> list(10);
std::vector<std::future<void>> asyncTasks;
for(int i = 0; i < 10; i ++){
asyncTasks.emplace_back(std::async(std::launch::async, &updateList, std::ref(list), i));
}
for(auto &f : asyncTasks){
f.get();
}
std::for_each(list.begin(),list.end(), [](auto v) {std::cout << v << " ";});
std::cout << "n";
}

//Better solution:
int heavy_work_calculation(int input) {
//Do the heavy stuff here
return input;
}
int main(){
std::vector<int> list(10);
std::iota(list.begin(), list.end(), 0);
std::transform(std::execution::par_unseq, list.begin(), list.end(),
list.begin(), heavy_work_calculation);
std::for_each(list.begin(),list.end(), [](auto v) {std::cout << v << " ";});
std::cout << "n";
}