多线程将映射分为多个部分
Multithreaded splitting a map into multiple sections
据说我有一个较大的std::map<SomeType1, std::vector<SomeType2>> my_map
,我需要对地图中的所有向量进行排序。目前我正在以一个线程运行:
for (auto& item : my_map)
{
std::sort(item.second.begin(), item.second.end(), &some_comparer);
}
使用上面的代码,我的CPU经常闲置〜15%,因此我认为我可以将地图分为较小的部分,并在单独的线程中对每个部分进行排序。
我想问,如何分配地图?例如,我想将其分为4个部分:
auto& section1 = my_map.divide(0, 0.25); // <~ how to apply this?
auto& section2 = my_map.divide(0.25, 0.5);
auto& section1 = my_map.divide(0.5, 0.75);
auto& section1 = my_map.divide(0.5, 1);
std::thread thread1([§ion1] { sort_for_me_pls(section1); });
std::thread thread2([§ion2] { sort_for_me_pls(section2); });
std::thread thread3([§ion3] { sort_for_me_pls(section3); });
std::thread thread4([§ion4] { sort_for_me_pls(section4); });
thread1.join();
thread2.join();
thread3.join();
thread4.join();
使用C 17,并行对向量排序很容易:
for (auto& [key, value] : my_map) {
std::sort(std::execution::par, std::begin(value), std::end(value), &some_comparer);
}
不幸的是,我不认为有任何编译器已经在此时在标准库中实现了算法的并行版本。不过,它可能很快就会发生(一年之内?(
您可以用类似的东西手动使用std::thread
:
std::vector<std::thread> threads;
for (auto& [key, value] : my_map) {
threads.emplace_back([&] {
std::sort(std::begin(value), std::end(value), &some_comparer);
});
}
for (auto&& t : threads) {
t.join();
}
您可以参考此问题的第一个答案(如何从std :: Map中检索所有键(或值(并将其放入向量?(,以查看如何获取地图中所有键的向量。完成此操作后,您可以传递到函数每个线程执行迭代器(或索引(以在密钥向量中开始及其应处理的键数。然后,每个线程只能对与密钥向量部分中的密钥关联的所有向量进行分类。该实现是不平凡的,因此我只将其留给您(例如,如果键少于4个键,您该怎么办,如果键的数量不均衡为4等,该怎么办。(。
。SNP提供了一个很好的答案来解决您的实际问题。但是,由于您的问题是要将地图分成多个部分,所以我认为您应该查看此答案,以解决类似(但更通用的(问题。您应该能够将此解决方案应用于地图或将其概括为与任何类型的容器一起使用。例如(split
将c
容器拆分为parts
零件(:
template <typename C>
using CItRange = boost::sub_range<const C>;
template <typename C>
std::vector<CItRange<C>> split(const C& c, size_t parts) {
const size_t step = c.size() / parts;
int remainder = c.size() % parts;
std::vector<CItRange<C>> slices;
auto it = begin(c);
while(it != end(c)) {
auto sliceBegin = it;
size_t remainderSpread = remainder-- > 0 ? 1 : 0;
std::advance(it, std::min(step + remainderSpread, (size_t)std::distance(it, end(c))));
slices.push_back(CItRange<C>{sliceBegin, it});
}
return slices;
}
您可以这样使用它:
std::map<int, std::vector<int>> myMap = {{1,{}}, {2,{}}, {3,{}}, {4,{}}, {5,{}}};
for(const auto& mapSlice : split(myMap, 2)) {
...
}
http://coliru.stacked-crooked.com/a/a/9d82fe79cc274dd7
相关文章:
- 多线程.如果我使用信号量,我可以在开始时创建很多线程还是应该只有几个线程?
- Qt多线程:如何更新两个QLabel?
- C 多线程,在并行多个线程时获得SegFault
- 多线程套接字编程服务器仅从 1 个客户端线程获取消息
- 多线程将映射分为多个部分
- C++多线程算法创建在同一 CPU 线程上运行的多个线程
- 在C 中将多个客户端连接到Windows中的单个服务器中的多线程
- 如何在多线程 c++ 17 程序中交换两个指针
- 在多线程程序中使用多个async_wait
- 无法使用OpenCV打开两个摄像头-多线程摄像头读取
- 通过不同的线程(多线程多孔客户端应用程序)使用多个球体
- Boost-在多个会话中对多个进程进行线程处理
- 多线程服务器在一个线程中处理多个客户端
- 具有四个队列的多线程生产者/消费者
- 在多线程环境中使用atomic保护两个变量
- 多线程:为什么两个程序比一个程序好
- CUDA 多线程:__threadfence不会阻止多个线程访问资源
- C++ - 通过多线程同时播放多个蜂鸣音
- 多线程 (openMP) - 多少个并行线程
- C++ 在同一台计算机中使用多个终端的多线程程序示例