Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何使用OpenMP并行化DFS?_C++_Parallel Processing_Openmp_Depth First Search - Fatal编程技术网

C++ 如何使用OpenMP并行化DFS?

C++ 如何使用OpenMP并行化DFS?,c++,parallel-processing,openmp,depth-first-search,C++,Parallel Processing,Openmp,Depth First Search,我正试图用OpenMP解决这个问题。我需要并行化深度优先遍历 这是算法: void dfs(int v){ 访问[v]=正确; 对于(int i=0;i

我正试图用OpenMP解决这个问题。我需要并行化深度优先遍历

这是算法:

void dfs(int v){
访问[v]=正确;
对于(int i=0;i
我尝试:

#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
矢量输出;
访问的病媒;
向量g;
int global=0;
无效dfs(整数v)
{
printf(“potoki%i”,omp_get_thread_num());

//coutOpenMP适用于数据并行代码,前提是事先知道工作量。对于像这样的图形算法,OpenMP不起作用

如果您只需要做代码中的内容(将元素推入向量),并行性会使速度变慢。即使图形上有很多GB的数据,瓶颈是内存而不是计算,多个CPU核也不会有帮助。此外,如果所有线程都将结果推送到同一个向量,则需要同步。此外,在现代处理器上,读取另一个CPU核最近写入的内存是昂贵的s、 甚至比缓存丢失还要严重

如果您除了复制整数之外还有大量CPU工作,请寻找OpenMP的替代方案。在Windows上,我通常使用
CreateThreadpoolWork
SubmitThreadpoolWork
API。在iOS和OSX上,请参阅grand central dispatch。在Linux上,请参阅cp_thread_pool_create(3)但与其他两个不同的是,我没有任何实践经验,只是找到了文档


无论您将使用何种线程池实现,您都可以在遍历图形时动态地将工作发布到线程池。OpenMP也有一个线程池,但API对于动态并行性来说不够灵活。

关键部分保护一个代码块,因此不会超过一个线程ad可以在任何给定的时间执行它。将对
dfs()
的递归调用放在一个关键部分内意味着没有两个任务可以同时进行该调用。此外,由于
dfs()
是递归的,任何顶级任务都必须等待整个递归完成,然后才能退出关键部分并允许另一个线程中的任务执行

您需要在不会干扰递归调用的情况下进行同步,并且只保护对共享数据的更新,而不提供其自身的内部同步。这是原始代码:

void dfs(int v){
访问[v]=正确;
对于(int i=0;i
一个简单但仍然并行的版本是:

void dfs(int v){
#pragma-omp-critical
{
访问[v]=正确;
对于(int i=0;i
在这里,任务一创建,代码就离开关键部分
是一个关键部分,这意味着即使有1000个并行递归调用,它们也会依次执行,而不是并行执行。由于不断的缓存失效和增加的OpenMP开销,它甚至会比顺序版本慢

一个重要的注意事项是,OpenMP关键部分,就像常规OpenMP锁一样,不是可重入的,因此线程很容易因在同一关键部分内部的递归调用中遇到同一关键部分而死锁,例如,如果任务立即执行而不是延迟。这是refore更好地使用OpenMP嵌套锁实现可重入的关键部分

该代码比sequential慢的原因是,它除了遍历图形外,不做任何其他事情。如果它在每个节点上做一些额外的工作,例如访问数据或计算节点本地属性,则可以在更新访问的
和未访问的邻居上的循环之间插入此工作:

void dfs(int v){
#pragma-omp-critical
访问[v]=正确;
//做些工作
#pragma-omp-critical
{
对于(int i=0;i
关键部分中的部分仍将按顺序执行,但由
//DO SOME WORK
表示的处理将并行重叠


通过使用一个大锁/关键部分来减少锁争用,有一些技巧可以加快速度。例如,可以使用一组OpenMP锁,并将访问的
索引映射到这些锁上,例如,使用所述的简单模运算。还可以停止在特定递归级别创建任务您发布的代码不完整,将无法编译。请计算主目录中
{…}
的配对。请提供一个。自3.0版(2008年)以来,OpenMP具有基于任务的并行性,非常适合动态工作负载,OP用它来完成他的任务。关键部分出现在错误的地方会减慢速度。