【发布时间】:2018-06-19 23:02:51
【问题描述】:
短背景(没必要)
我一直在努力为Scikit-Learn 编写一个替代方案(需要较少资源?)mean shift C++ 模块。
在 C++ 方面,我一直在使用 nanoflann 库来构建和搜索 KD-Tree。
基本上我有两个 numpy 数组,我通过 Cython 将它们传递给我的 C++ MeanShift 函数,然后返回找到的集群中心列表。
事实证明它要快一点,大约 7 倍(我仍在积极研究它)。
我的问题:
我想并行化我的 C++ 代码中最昂贵的部分,比如用于收敛的 for 循环,但是,由于这个 C++ 模块将被导入 python,我希望以最安全的方式这样做& 简单的方法。
我考虑过使用 OpenMP,您有什么建议吗?
谢谢! 祝你有美好的一天。
编辑/编码 sn-p
谢谢@bivouac0,我现在可以编译整个了。
现在我正在与逻辑/技术方面作斗争。 让我给你写一个我想要并行化的代码。
我有一个std::vector<std::pair<size_t, double> > > matches 向量和一个相当大的double samples[N] 数组。
我想使用存储在matches 向量中的对的第一个元素来计算对更大samples 数组的访问索引(参见下面的代码):
这是执行此操作的方法:
typedef std::vector<std::pair<size_t, double> > searchResultPair;
double* calcMean(size_t nMatches, searchResultPair matches,
double* samples) {
/*
*/
double* returnArray = new double[3];
returnArray[0] = 0;
returnArray[1] = 0;
returnArray[2] = 0;
double x = y = z = 0;
for (size_t i = 0; i < nMatches; i = i + 1) {
x = x + samples[3 * (matches[i].first)];
y = y + samples[3 * (matches[i].first) + 1];
z = z + samples[3 * (matches[i].first) + 2];
}
returnArray[0] = x/nMatches;
returnArray[1] = y/nMatches;
returnArray[2] = z/nMatches;
return(returnArray);
}
有没有办法同时访问matches[i].first 变量?
我已尝试使用 #pragma omp parallel for reduction(+:x,y,z) num_threads(n_threads),但它会降低性能(1 线程 > 2 线程 > 4 线程 > 8 线程等等...)。
我的问题有任何意义吗?我在哪里弄错了吗?
管理并行 n_threads 团队以计算部分和 x,y,z 可能只是开销,因为 vector 中的元素是连续存储的...
我可以将上面的 for 循环分成 3 个部分并尝试并行化每个部分。 这是个好主意吗?
那边的计算嵌套在 while 中,嵌套在另一个 for 循环中,这是整个模块中最重要的方法。
【问题讨论】:
-
OMP 非常简单。我倾向于在大多数情况下将它用于并行 for 循环的包装器中,这为它们提供了类似于 TBB 的功能样式接口,例如:
pfor(start_index, end_index, chunk_size, func);和pfor_each(c.begin(), c.end(), chunk_size, func);还可以轻松地在不同的并行库之间进行交换以比较它们的性能特征。 -
我在 c++ 代码中使用了 OMP,它可以毫无问题地导入到 python 中。所有 OMP 指令都隐藏在 c++ 函数调用之后,因此您将它们导入 python 的事实有点无关紧要。您只需要确保在构建模块时应用正确的 c++ 编译器指令来启用 OMP。
-
@bivouac0 我尝试过使用 OMP,但遇到了 ImportError python-side (
undefined symbol: GOMP_parallel)。我添加了 -fopenmp 标志,但我可能会误认为其他编译选项(甚至是编译器本身!)。有什么建议吗? -
如果没有实际数据,其他人很难帮助找到答案,但是我首先尝试在单个循环中使用
omp parallel for,看看它是否会加速累积。然后我会查看omp sections以并行化不同的 for 循环。您应该能够获得不错的加速,但有时需要进行一些试验才能获得正确的组合。尝试编写尽可能紧凑的代码。有时这有助于 OMP 编译一个快速的解决方案。如果您需要更多帮助,您可能需要发布项目的一部分,其中包含准备好运行的代码和数据。 -
嘿@bivouac0,谢谢你的回答。我也在 CodeReview 上问过,这里是full code
标签: python c++ multithreading scikit-learn