OpenMP 与向量的向量并行
OpenMP parallel for with vector of vectors
>我有一个大小为W x H的固定大小的二维矩阵,矩阵中的每个元素都是一个std::vector。数据存储在具有线性索引的向量中。我正在尝试找到一种同时填充输出向量的方法。这里有一些代码来指示我正在尝试做什么。
#include <cmath>
#include <chrono>
#include <iostream>
#include <mutex>
#include <vector>
#include <omp.h>
struct Vector2d
{
double x;
double y;
};
double generate(double range_min, double range_max)
{
double val = (double)rand() / RAND_MAX;
return range_min + val * (range_max - range_min);
}
int main(int argc, char** argv)
{
(void)argc;
(void)argv;
// generate input data
std::vector<Vector2d> points;
size_t num = 10000000;
size_t w = 100;
size_t h = 100;
for (size_t i = 0; i < num; ++i)
{
Vector2d point;
point.x = generate(0, w);
point.y = generate(0, h);
points.push_back(point);
}
// output
std::vector<std::vector<Vector2d> > output(num, std::vector<Vector2d>());
std::mutex mutex;
auto start = std::chrono::system_clock::now();
#pragma omp parallel for
for (size_t i = 0; i < num; ++i)
{
const Vector2d point = points[i];
size_t x = std::floor(point.x);
size_t y = std::floor(point.y);
size_t id = y * w + x;
mutex.lock();
output[id].push_back(point);
mutex.unlock();
}
auto end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end - start;
std::cout << "elapsed time: " << elapsed_seconds.count() << "sn";
return 0;
}
问题是启用 openmp 后代码要慢得多。我找到了一些使用缩减填充 std::vector 的例子,但我不知道如何使其适应向量的向量。任何帮助是感激的,谢谢!
您可以采取一些措施来提高性能:
我会预分配保存Vector2d
类的第二个向量,因为每次您push_back
新Vector2d
并且超出std::vector
的容量时,它都会重新分配。因此,如果您不在乎在std::vector
中初始化Vector2d
,我将简单地使用:
std::vector<std::vector<Vector2d> > output(num,
std::vector<Vector2d>(num, Vector2d(/*whatever goes in here*/)));
然后在你的 for 循环中,你可以通过 operator[]
访问第二个向量中的元素,这允许你摆脱锁。
#pragma omp parallel for
for (size_t i = 0; i < num; ++i)
{
const Vector2d point = points[i];
size_t x = std::floor(point(0));
size_t y = std::floor(point(1));
size_t id = y * w + x;
output[id][i] = num;
}
虽然我不确定,但前面提到的方法适用于您想要做的事情。 否则,您可以为每个std::vector<Vector2d>
保留存储,这将为您留下初始循环:
std::vector<std::vector<Vector2d> > output(num, std::vector<Vector2d>());
for(int i = 0; i < num; ++i) {
output[i].reserve(num);
}
#pragma omp parallel for
for (size_t i = 0; i < num; ++i)
{
const Vector2d point = points[i];
size_t x = std::floor(point(0));
size_t y = std::floor(point(1));
size_t id = y * w + x;
mutex.lock();
output[id].push_back(point);
mutex.unlock();
}
这意味着你摆脱了向量重新分配,但你仍然有互斥锁......
相关文章:
- 写入向量<向量<bool>>
- 函数向量_指针有不同的原型,我可以构建一个吗
- std::向量与传递值的动态数组
- 将值指定给向量(2D)的向量中的某个位置
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 如何使用向量的template_back函数
- 使用并行参数向量调用元素向量的成员函数
- 检查两个向量是否并行的最有效方法
- 使用异步/期货并行和并发计算向量的范数
- 并行算法将向量的元素分配到另一个元素的元素
- C++:快速/并行计算两个"std::vector<double>"向量之间的L1距离
- OpenMP 与向量的向量并行
- 使用多个线程的并行向量乘法比顺序乘法需要更长的时间
- 并行程序中的多图或排序向量
- 使用异步C++进行向量的并行乘法
- 在OpenMP并行区域中使用向量push_back是否安全
- 在并行追加时,使用向量列表和向量的向量对性能的影响
- 并行乘法向量矩阵
- 在OPENMP中并行化矩阵向量的加法
- 多个排序向量与固定线程数的并行交集