c++ - 在 OpenMP 中读取/写入共享向量会减慢程序速度
问题描述
我正在努力将 OpenMP 用于分片向量。在我的真实代码中,我有一个存储数组的向量,我希望使用 OpenMP 来加速一个 for 循环,我必须在其中访问向量内的所有这些元素并计算与截止范围内的所有其他元素的交互。这意味着,在向量的不同块中,交互的计算是独立的。并且计算是一个方向和周期性的,从第一个元素开始,到最后一个元素与前几个元素相互作用。我只是希望使用两个线程来测试可行性,并将工作负载分为两部分,我认为它们是相互独立的。
但是单核的仿真时间是:real 0m2.417s user 0m2.149s sys 0m0.011s
多线程是:真正的 0m4.490s 用户 0m8.371s sys 0m0.024s
更新
感谢人们已经给了我一些建议,我非常感谢。我想给出我的代码的更多细节:所以有一个向量有 100 个元素,每个元素将与右手相邻的 9 个元素进行计算。这很棘手,因为实际上这项工作可以分为 10 种独立的工作,所以我天真地认为这适合并行计算,但如果线程没有很好地组织起来,很可能会出现竞态条件. 那么,我如何具体说明使用 OpenMP 的工作负载,以确保同时不同的线程正在读取/写入向量的不同部分?
#include <stdio.h>
#include <omp.h>
#include <vector>
#include <array>
#include <iostream>
using namespace std;
auto k = 50000;
auto cutOff = k/10;
void testFunc(vector<int> &positions){
#pragma omp parallel for num_threads(2) schedule(static, k/2)
for (int i = 0; i< k ; i++){
for (int j = i; j<i+cutOff; j++){
j=(j<=k?j:j-k);
positions[i]+=1;
positions[j]-=1;
}
}
}
int main()
{
vector<int> pos;
pos.resize(k);
for (int i = 0; i<pos.size(); i++){
pos[i]=rand() % 100;
}
printf("first value = %d\n", pos[0]);
testFunc(pos);
printf("last value = %d\n", pos[0]);
}
解决方案
正如您正确观察到的那样,作品可以分为独立的块或“部分”,例如:
void testFunc(vector<int> &positions){
int numSections = cutOff;
for (int section = 0; section < numSections; ++section) {
#pragma omp parallel for schedule(static)
for (int i = section; i < k ; i += cutOff) {
for (int offset = 0; offset < cutOff; ++offset) {
int j = i + offset;
if (j >= k)
j -= k;
positions[i] += 1;
positions[j] -= 1;
}
}
}
}
请注意,这只有k
在实际上可以被cutOff
!整除时才能正常工作。(考虑k = 11
和cutOff = 10
。)
cutOff
如果很大(例如,如果它是 的 10% ),那么启动许多并行部分看起来会产生很多开销k
,但这更多是因为算法本身是二次的(它修改2 * k * cutOff = 0.2 * k * k
了元素)。因此,如果您k
的规模很大,那么并行化仍然很值得。
推荐阅读
- excel - 从工作簿复制和粘贴的问题(循环错误)
- sql - SQL区间查询
- python - 如何阻止 Scrapy CrawlSpider 跟踪比要求更多的 URL?
- reactjs - 为什么增加数量的按钮不起作用(模拟喜欢)?如何解决这个问题?
- javascript - 单击按钮时更改文本的正确函数语法
- prometheus - Alertmanager 未向接收者发送警报
- python - Tkinter 如何在 Microsoft Windows 上工作?
- c# - 更改 URL 参数 MVC
- django - NGINX + Gunicorn:编写器中的零大小缓冲区
- spring-boot - 如何忽略多项目 Kotlin Spring Boot 应用程序的根项目的 gradle 构建?