C++中的多线程迭代



我是c++的新手,我正在尝试迭代应用于作为迭代器的多映射的equal_range(key)的结果。现在,我可以使用for循环以及result.firstresult.second值来迭代结果,如本例所示:

#include <iostream>
#include <map>
int main ()
{
std::multimap<char,int> mymm;
mymm.insert(std::pair<char,int>('a',10));
mymm.insert(std::pair<char,int>('b',20));
mymm.insert(std::pair<char,int>('b',30));
mymm.insert(std::pair<char,int>('b',40));
mymm.insert(std::pair<char,int>('c',50));
mymm.insert(std::pair<char,int>('c',60));
mymm.insert(std::pair<char,int>('d',60));

auto ret = mymm.equal_range('b');
for (auto it=ret.first; it!=ret.second; ++it)
std::cout << ' ' << it->second;
} 

在我的实际情况下,我需要更快地迭代(在短时间内迭代数千行(,所以我尝试使用多个线程进行迭代。然而,我无法做到这一点,因为我的想法是将迭代器拆分为不同的部分,然后在不同的线程中对每个部分进行迭代。但这是不可能的,因为我不能像it = it + 10那样开始在不同的位置上迭代。

因此,本质上我需要将一系列非随机访问迭代器划分为多个较小的范围。有什么安全的方法吗?

正如评论中所指出的,您的问题可以归结为"如何将非随机访问迭代器的范围划分为多个较小的范围";。一旦你得到了,你可以把这些较小的范围交给多个线程。

it不是随机访问迭代器时,不能使用it + 10。但是,您可以使用std::advance来推进迭代器。

举例说明:

#include <iostream>
#include <map>
#include <vector>
template <typename IT>
std::vector<IT> split_range(IT begin, IT end,size_t chunksize){
std::vector<IT> result;
auto it = begin;
result.push_back(it);
size_t total = 0;
size_t size = std::distance(begin,end);
while (total + chunksize < size){
std::advance(it,chunksize);
result.push_back(it);
total += chunksize;
}
if (it != end) result.push_back(end);
return result; 
}

int main ()
{
std::multimap<char,int> mymm;
mymm.insert(std::pair<char,int>('a',10));
mymm.insert(std::pair<char,int>('b',20));
mymm.insert(std::pair<char,int>('b',30));
mymm.insert(std::pair<char,int>('b',40));
mymm.insert(std::pair<char,int>('c',50));
mymm.insert(std::pair<char,int>('c',60));
mymm.insert(std::pair<char,int>('d',60));

auto ret = mymm.equal_range('b');

auto splitted = split_range(ret.first,ret.second,1);
for (auto it = splitted.begin(); std::next(it) != splitted.end(); ++it){
std::cout << "printing one chunkn";
for (auto it2 = *it; it2 != *std::next(it); ++it2){
std::cout << ' ' << it2->second << "n";
}
}
}

CCD_ 8可能不是最有效的。std::advance是有代价的,您需要在单个线程中对整个范围进行一次迭代。而且std::distance在非随机访问迭代器上也不是免费的(基本上需要第二次迭代整个范围(。不过,一旦划分了范围,就可以使用多个线程并行处理子范围。

并行化工作的一种方法是使用C++17中添加的<execution>策略。

std::for_each一起使用时,它可能看起来像这样:

#include <algorithm>
#include <execution>
#include <iostream>
#include <map>
int main() {
std::multimap<char, int> mymm;
mymm.insert(std::pair<char, int>('a', 10));
mymm.insert(std::pair<char, int>('b', 20));
mymm.insert(std::pair<char, int>('b', 30));
mymm.insert(std::pair<char, int>('b', 40));
mymm.insert(std::pair<char, int>('c', 50));
mymm.insert(std::pair<char, int>('c', 60));
mymm.insert(std::pair<char, int>('d', 60));
auto [begin, end] = mymm.equal_range('b');
std::for_each(std::execution::par, begin, end,
[](const auto& p)
{
std::cout << ' ' << p.second;
}
);
}

最新更新