gpt4 book ai didi

c++ - 当我不添加/删除键时,可以并行使用 std::map 吗?

转载 作者:行者123 更新时间:2023-12-02 05:47:08 24 4
gpt4 key购买 nike

我有一个程序使用了很多 std::map 结构。现在我想将它们与多个线程一起使用,并假设插入或删除键可能会改变整个数据结构并并行破坏它。但是当我不添加新 key 时,应该没问题,对吗?

以下程序显示了我想要执行的操作:

#include <omp.h>                                                                

#include <iostream>
#include <map>

int main(int const argc, char const *const *const argv) {
// Take a map and allocate the elements, but not fill them at this point.
std::map<int, int> map;
int size = 10000;
for (int i = 0; i < size; ++i) {
map[i];
}

// Go through the elements in parallel and write to them, but not create any
// new elements. Therefore there should not be any allocations and it should
// be thread-safe.
#pragma omp parallel
{
int const me = omp_get_thread_num();
#pragma omp for
for (int i = 0; i < size; ++i) {
map[i] = me;
}
}

// Now all threads access all the elements of the map, but as the map is not
// changed any more, nothing bad should happen.
#pragma omp parallel
{
int const me = omp_get_thread_num();
int self = 0;

for (int i = 0; i < size; ++i) {
if (map[i] == me) {
++self;
}
}

#pragma omp critical(cout)
std::cout << "Thread " << me << " found " << self << " entries.\n";
}
}

然后我用以下代码编译它:

$ g++ -fopenmp -O3 -Wall -Wpedantic -g -fsanitize=address -o concurrent-map concurrent-map.cpp

这对于四个线程来说似乎工作得很好。如果我注释掉第一个 for 循环并让线程填充映射,它将因段错误而崩溃,正如我所料。

当然,我不能按照我的想法证明 std::map 是线程安全的,但它至少没有证明负面的。我可以以这种方式并行使用 std::map 吗?

最佳答案

我不认为使用map[i]特别是对于所有 C++ 实现来说都是线程安全的,即使它不插入新元素。标准不要求operator[]避免关联容器的数据竞争:

部分[container.requirement.dataraces]/1 C++17 标准草案的 包含不应导致数据争用的函数列表,即使它们不是 const 。该列表包括findat ,但不是operator[] .

因此您需要使用findat而不是operator[] 。特定的实现可能会提供更强的保证,并且如果 map[i] 则可能会出现这种情况。没有插入新元素,但您需要使用编译器/标准库文档进行检查。

除此之外,访问,甚至修改容器的不同元素总是没问题的( vector<bool> 除外),请参阅标准中的下一段。

关于c++ - 当我不添加/删除键时,可以并行使用 std::map 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58692995/

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