C++ 用两个语句并行while循环(Floyd循环检测算法)
我将尝试并行化以下简单的C++ 用两个语句并行while循环(Floyd循环检测算法),c++,multithreading,algorithm,performance,openmp,C++,Multithreading,Algorithm,Performance,Openmp,我将尝试并行化以下简单的,同时使用OpenMP将循环成两个线程(我第一次尝试使用此技术)。我试着同时使用,部分和任务。尽管我把它分成了两个线程并得到了正确的结果,但性能还是慢得令人难以接受 while ( tortoise != hare ) { tortoise = f ( tortoise ); hare = f ( f ( hare ) ); } 注意:f是函数对象的常量&(即它有一个T操作符()(常量T&r)) 操作符()实现如下(d是函数对象的成员变量): 我的第一个
,同时使用OpenMP将循环成两个线程(我第一次尝试使用此技术)。我试着同时使用,部分
和任务
。尽管我把它分成了两个线程并得到了正确的结果,但性能还是慢得令人难以接受
while ( tortoise != hare ) {
tortoise = f ( tortoise );
hare = f ( f ( hare ) );
}
注意:f
是函数对象的常量&
(即它有一个T操作符()(常量T&r)
)
操作符()
实现如下(d
是函数对象的成员变量):
我的第一个想法是创建线程的开销。因此,我在封闭函数的一开始就创建了团队
(它本身只被调用一次,而上面的while
-循环可以进行大量迭代(它是函数的一部分)
我在这里省略了我所有的#pragma omp…
尝试,因为它们都会导致糟糕的性能
编辑:
基于@templatetypedef的答案,我尝试了Brent的算法。因为我需要在-循环时对Floyd的第二个和第三个注入一些计算(构建预循环和循环值的数字数组,以及使用Horner方案计算多项式)Brent没有为我提供添加此代码的要点。因此,我更喜欢Floyd。完整的代码可以找到。我认为这里的问题是,您尝试并行化的代码不能很好地并行化。请这样想:每个线程基本上需要做十几个算术运算来提升其指针,但随后需要s与另一个线程同步,以确认值不相同,并且在两个线程完成之前无法进行任何部分处理。简单地锁定或解锁互斥锁的成本是,这可能是计算其中一个乌龟或兔子步骤所需的时间。因此,每个线程最终可能只执行了大约t他的工作量与单循环迭代相同,而且可能更多,所以我严重怀疑您是否能通过这种方式获得加速
现在,可能有效的方法是使用像Brent的循环查找算法这样的算法,它比Floyd的算法进行的比较少,而且通常收敛得更快。这很可能会让你更快地找到循环。我认为这里的问题是,你试图并行化的代码不能很好地并行化。Th这样理解:每个线程基本上需要做十几个算术运算来推进其指针,但随后需要与另一个线程同步,以确认值不相同,并且在两个线程完成之前不能进行任何部分的进程。简单地锁定或解锁互斥锁的成本是,这可能是ab计算一个龟步或兔步所需的时间。因此,每个线程最终可能完成的工作量与单个循环迭代所需的工作量几乎相同,而且可能更多,因此我严重怀疑您是否会通过这种方式获得加速
现在,可能有效的方法是使用像Brent的循环查找算法这样的算法,它比Floyd的算法进行的比较少,而且通常收敛速度更快。这很可能会让你更快地找到循环。如何实现f
呢?你真的认为多线程处理会加快这一速度吗每个线程基本上都会调用f,然后做大量的工作来与另一个线程同步?@templatetypedef因为我认为这两个语句可以并行处理,所以我想在多核CPU上尝试一下。我添加了T operator()(const T&r)的实现
问题的答案。f
是如何实现的?考虑到每个线程基本上都会调用f,然后做大量的工作来与另一个线程同步,你真的认为多线程处理会加快速度吗?@templatetypedef因为我认为这两条语句可以并行处理,所以我想在多线程上尝试一下我已经添加了T操作符()的实现(const T&r)
回答这个问题。好吧,那么我对开销的假设可能是正确的。我已经尝试了Brent算法,但是我在Floyd的第二个和第三个中插入了一些额外的代码,就像我在时所做的那样。但是如果Brent的并行化更有希望。我必须试着理解这个变体,或者如果性能得到了提高,我会它太大了,甚至没有注入我的代码,但之后再做。-我会等待更多的想法,否则我会接受你的答案。阅读理解为什么任何试图获得弗洛伊德算法显著并行加速的尝试都是注定的,即使是在理想的理论机器上。周期检测的工作和跨度都将与周期成正比长度,因此它们的商为O(1).好的,所以我对开销的假设可能是正确的。我已经尝试了Brent算法,但是我在Floyd的第二个和第三个while
中插入了一些额外的代码。但是如果Brent的并行化可能更有希望。我必须试着理解这个变体,或者性能增益是否如此巨大,即使不是inj检查我的代码,但以后再做。-我会等待更多的想法,否则我会接受你的答案。阅读以理解为什么任何试图获得弗洛伊德算法显著并行加速的尝试都是注定的,即使是在理想的理论机器上。周期检测的功和跨度都将与周期长度成正比,因此它们的qu通知将是O(1)。
T operator() ( const T &r ) const {
return ( ( r % d ) * 10 );
}