【发布时间】:2016-03-31 14:51:14
【问题描述】:
我有一个算法,其目标是填充向量。出于性能考虑,算法的迭代分布在 OpenMP 线程中。我想知道哪种方式可以提供更好/更安全的填充向量的方式。
请注意,向量的顺序必须一致(即 vec1 的值 n 必须来自与 vec2 的值 n 相同的迭代。)
假设 1:
std::vector<BasicType> vec1;
std::vector<BasicType> vec2;
#pragma opm parallel for
for(...)
{
// Do some intensive stuff to compute val1 and val2
// ...
#pragma omp critical
{
vec1.push_back(val1);
vec2.push_back(val2);
}
}
// Then go on to work with vec1 and vec2...
假设 2:
std::vector<BasicType> vec1;
std::vector<BasicType> vec2;
#pragma opm parallel
{
std::vector<BasicType> vec1local;
std::vector<BasicType> vec2local;
#pragma omp for
for(...)
{
// Do some intensive stuff to compute val1 and val2
// ...
vec1local.push_back(val1);
vec2local.push_back(val2);
}
#pragma omp critical
{
// See note 1 below
vec1.insert(vec1.end(), vec1local.begin(), vec1local.end());
vec2.insert(vec2.end(), vec2local.begin(), vec2local.end());
}
}
// Then go on to work with vec1 and vec2...
注 1: 这取自 Best way to append vector to vector
注 2: 似乎 val1 和 val2 可以组合在某个对象中以保持一致性并仅使用一个向量,但目前对于算法的其余部分来说似乎不切实际。
注 3: 给出一个数量级,for 循环包含大约 100 次迭代,分布在 4 个线程中。除了极少数例外,每次迭代都应具有相同的工作负载(这会带来关键部分几乎同时发生的问题。)
注 4: 仅作记录,整个事情处理图像稳定,并在 Tegra K1 架构上运行。使用的编译器是 gcc 4.8.4。
【问题讨论】:
-
如果你像这样合并你的向量,你会想要使用移动迭代器来节省复制这么多。
-
对的填充顺序重要吗?我的意思是你在串行中填写 (val1,val2)_0, 然后 ),(val1,val2)_1, ...(val1,val2)_n-1。如果它必须像这样,那么你的假设都不会成立。
-
此外,如果您提前知道向量的元素数量,则没有理由使用向量。只需使用数组或像Zulan's answer 中的数组一样访问向量。
-
@Zboson 不,顺序无关紧要,因为在此过程的后期会进行一些排序和过滤。后者是为什么我更喜欢使用向量而不是数组。