我实现了我的模拟的并行版本(使用基于大量内存的Wolff算法进行模型模拟),但它比串行版本慢3倍。
O不知道该怎么办。
以下是代码的一些解释:
对于每个线程,我有一个int
s(大小为60 * 60 * 60,100 * 100 * 100)的3d数组,这些数组保存在heap
中(由malloc()
分配) 。
几乎每个线程所做的一切都依赖于这些数组(这些数组的大量读写)。
因为数组在堆中,所以比串行版本慢?
或者因为我的程序是基于内存的(大量读写),它会慢一些吗?
或者我错过了什么?
谢谢!
void start()
{
/*initialize gnuplot*/
init_gnuplot(config0);
#pragma omp parallel
{
#pragma omp single
{
calculate_threads_T_interval();
}
#pragma omp barrier
config c = config0;
c.T_initial = thread_T_start[omp_get_thread_num()];
c.T_final = thread_T_end[omp_get_thread_num()];
/*create new system*/
System *system = newSystem(c);
/*measure initial values of M and E*/
measure_Magnetization(system);
measure_Energy(system);
/*change system T to its initial value*/
system->T = c.T_initial;
#pragma omp barrier
/*run the algorithm*/
run_T_interval(system, c);
}
}
答案 0 :(得分:0)
如果没有看到您的代码,很难肯定回答,但是减速的一个潜在原因是OpenMP在创建/管理线程时会有一些开销。如果任务加速小于开销,您将看到更长的执行时间。
堆与堆栈访问时间通常可以忽略不计,并且取决于体系结构,但您不应该看到与之相比存在显着差异。如果您正在与它们也存储在堆中的顺序版本进行比较,那么这没有任何影响。
我会检查您是否正确使用OpenMP。首先尝试在几段代码上实现它并看到效果。
答案 1 :(得分:0)
在并行程序中使用像barrier这样的同步操作是很昂贵的,因为所有线程都必须等待最慢的线程完成。在您的代码结构中,有两个同步点。
首先,您生成了一定数量的线程,但只有一个线程正在计算线程间隔,而其他线程处于空闲状态并等待此单个线程完成执行。
如果您可以先调用calculate_threads_T_interval()然后生成线程,则可以消除代码中的一个同步点,这将有助于提高速度。
如果没有查看完整的代码,很难说问题是什么,但对我来说,这是一个纯粹基于你给出的伪代码的小优化。
这是对omp屏障构造及其对性能的影响及其可能产生的其他可能问题的良好解读http://jakascorner.com/blog/2016/07/omp-barrier.html