考虑到当今多核和多处理硬件的巨大重要性,试图掌握当前人们实际编写并行代码的方式.对我来说,看起来主流范式是pthreads(POSIX线程),它在Linux上是原生的,可在Windows上使用.HPC人员倾向于使用OpenMP或MPI,但似乎StackOverflow上没有这些.或者你依靠Java线程,Windows线程API等而不是便携式标准?在您看来,建议的并行编程方式是什么?
或者你正在使用更多异国情调的东西,如Erlang,CUDA,RapidMind,CodePlay,Oz,甚至是亲爱的老奥卡姆?
澄清:我正在寻找非常便携的解决方案,适用于各种主机架构上的Linux,各种unix等平台.Windows是一种罕见的案例,非常适合支持.所以C#和.net在这里真的太狭隘,CLR是一个很酷的技术,但是他们可以为Linux主机发布它,这样它就像JVM,Python,Erlang或任何其他可移植语言一样普遍.
基于C++或JVM:可能是C++,因为JVM往往会隐藏性能.
MPI:我同意甚至HPC人员都认为它是一种难以使用的工具 - 但是对于在128000处理器上运行,它是解决map/reduce不适用的问题的唯一可扩展解决方案.但是,消息传递非常优雅,因为它是唯一可以很好地扩展到本地内存/ AMP,共享内存/ SMP,分布式运行时环境的编程风格.
一个有趣的新竞争者是MCAPI.但我认为没有人有时间对此有任何实际经验.
总的来说,情况似乎是有许多我不了解的有趣的微软项目,而且Windows API或pthreads是实践中最常见的实现.
我意识到减少仅适用于C++中的POD类型.您将如何实现复杂类型累加器的减少?
complex<double> x(0.0,0.0), y(1.0,1.0);
#pragma omp parallel for reduction(+:x)
for(int i=0; i<5; i++)
{
x += y;
}
Run Code Online (Sandbox Code Playgroud)
(注意到我可能已经遗漏了一些语法).似乎一个明显的解决方案是将实部和虚部分成临时双重,然后积累在那些上.我想我正在寻找优雅,这似乎......不仅仅是漂亮.这是典型的方法吗?
我有一些代码,我想以下列方式使用OpenMP:
std::vector<int> v(1000);
# pragma omp parallel for
for (int i = 0; i < 1000; ++i) {
v[i] = i;
}
Run Code Online (Sandbox Code Playgroud)
我已经读过,在多个线程写入单个容器的情况下,STL向量容器不是线程安全的,这意味着我需要在进行任何写入之前锁定向量; 但是,我也被告知上面的写操作在某种程度上是"原子的",所以上面没有竞争条件.有人可以澄清一下吗?
嗨,只是想知道这是否是正确的循环,但有两个减少的正确方法,这是正确的方法下面?这也可以减少两次以上.有一个更好的方法吗?还有没有机会将它与MPI_ALLREDUCE命令集成?
heres the psuedo code
#pragma omp parallel for \
default(shared) private(i) \
//todo first reduction(+:sum)
//todo second reduction(+:result)
for loop i < n; i ++; {
y = fun(x,z,i)
sum += fun2(y,x)
result += fun3(y,z)
}
Run Code Online (Sandbox Code Playgroud) 我想知道在OMP关键部分中抛出C++异常是否安全.
#pragma omp critical (my_critical_section)
{
...
throw my_exception("failed")
...
}
Run Code Online (Sandbox Code Playgroud)
g ++不抱怨.我很困惑,因为它抱怨return关键部分内的陈述.它返回错误:invalid exit from OpenMP structured block我写的时候
#pragma omp critical (my_critical_section)
{
...
return;
...
}
Run Code Online (Sandbox Code Playgroud)
那么,为什么离开临界区有一个例外是可以的,但是留下一个返回语句是不行的?
可以在CUDA文件中使用openMP pragma(不在内核代码中)吗?
我将结合gpu和cpu计算.但是nvvc编译器失败,"无法找到未知选项'openmp'",如果我将porgram与openmp选项链接(在linux下)
一种解决方法是仅在c/c ++文件中使用openMP-statments.
基于这个线程,OpenMP和STL向量,哪些数据结构是并行for循环中共享 std :: vector的好选择?主要方面是速度,矢量可能需要在循环期间调整大小.
我对于在代码的并行部分中指定线程数的方法感到很困惑.我知道我可以用:
#pragma omp parallel for num_threads(NB_OF_THREADS)到目前为止我收集的前两个是等价的.但是第三个呢?有人可以提供更详细的差异说明,我无法在互联网上找到有关1/2和3之间差异的任何信息.
我正在开发大密集矩阵乘法代码.当我对代码进行分析时,它有时会获得我的四个核心系统中大约75%的峰值触发器,而其他时间则大约为36%.在执行代码之间效率不会改变.它要么以75%开始并继续保持效率,要么从36%开始并继续保持这种效率.
我已经将问题追溯到超线程以及我将线程数设置为4而不是默认值8的事实.当我在BIOS中禁用超线程时,我一致地获得大约75%的效率(或者至少我从未看到大幅下降到36%).
在我调用任何并行代码之前omp_set_num_threads(4).我export OMP_NUM_THREADS=4在运行代码之前也尝试过,但它似乎是等效的.
我不想在BIOS中禁用超线程.我想我需要将四个线程绑定到四个核心.我已经测试了一些不同的情况,GOMP_CPU_AFFINITY但到目前为止,我仍然存在效率为36%的问题. 超线程和核心的映射是什么? 例如,线程0和线程1对应于同一个核心和线程2,线程3对应另一个核心吗?
如何在没有线程迁移的情况下将线程绑定到每个核心,这样我就不必在BIOS中禁用超线程? 也许我需要研究使用sched_setaffinity?
我当前系统的一些细节:Linux内核3.13,GCC 4.8,Intel Xeon E5-1620(四个物理内核,八个超线程).
编辑:到目前为止,这似乎运作良好
export GOMP_CPU_AFFINITY="0 1 2 3 4 5 6 7"
Run Code Online (Sandbox Code Playgroud)
要么
export GOMP_CPU_AFFINITY="0-7"
Run Code Online (Sandbox Code Playgroud)
编辑:这似乎也运作良好
export OMP_PROC_BIND=true
Run Code Online (Sandbox Code Playgroud)
编辑: 这些选项也很好用(gemm是我的可执行文件的名称)
numactl -C 0,1,2,3 ./gemm
Run Code Online (Sandbox Code Playgroud)
和
taskset -c 0,1,2,3 ./gemm
Run Code Online (Sandbox Code Playgroud) 给定n部分和,可以将log2并行步骤中的所有部分和相加.例如,假设有八个线程与八个部分和:s0, s1, s2, s3, s4, s5, s6, s7.这可以在这样的log2(8) = 3连续步骤中减少;
thread0 thread1 thread2 thread4
s0 += s1 s2 += s3 s4 += s5 s6 +=s7
s0 += s2 s4 += s6
s0 += s4
Run Code Online (Sandbox Code Playgroud)
我想用OpenMP做这个,但我不想使用OpenMP的reduction子句.我想出了一个解决方案,但我认为可以使用OpenMP的task子句找到更好的解决方案.
这比标量加法更通用.让我选择一个更有用的情况:一个数组减少(见这里,这里,并在这里为更多关于阵列减少).
假设我想在阵列上进行数组缩减a.下面是一些代码,它们为每个线程并行填充私有数组.
int bins = 20;
int a[bins];
int **at; // array of pointers to arrays
for(int i = 0; i<bins; i++) a[i] = 0;
#pragma omp …Run Code Online (Sandbox Code Playgroud)