考虑:
void saxpy_worksharing(float* x, float* y, float a, int N) {
#pragma omp parallel for
for (int i = 0; i < N; i++) {
y[i] = y[i]+a*x[i];
}
}
和
void saxpy_tasks(float* x, float* y, float a, int N) {
#pragma omp parallel
{
for (int i = 0; i < N; i++) {
#pragma omp task
{
y[i] = y[i]+a*x[i];
}
}
}
使用任务和omp并行指令有什么区别?为什么我们可以编写递归算法,例如合并排序与任务,但不能写工作共享?
答案 0 :(得分:23)
我建议您查看劳伦斯利弗莫尔国家实验室的OpenMP教程,here。
您的特定示例是使用OpenMP任务不的示例。第二个代码创建N
次线程任务的数量(因为丢失的}
旁边的代码中有错误;我稍后会再回过头来看),每个任务只执行一次简单的计算。正如你在this question的答案中所看到的,任务的开销将是巨大的。除了第二个代码在概念上是错误的。由于没有工作共享指令,所有线程都将执行循环的所有迭代,而不是N
任务,N
次创建任务线程数。它应该用以下方式之一重写:
单一任务制作人 - 普通模式,NUMA不友好:
void saxpy_tasks(float* x, float* y, float a, int N) {
#pragma omp parallel
{
#pragma omp single
{
for (int i = 0; i < N; i++)
#pragma omp task
{
y[i] = y[i]+a*x[i];
}
}
}
}
single
指令只会使循环在单个线程内运行。所有其他线程都会跳过它并在single
结构的末尾点击隐式屏障。由于障碍包含隐式任务调度点,等待线程将在可用时立即开始处理任务。
并行任务制作人 - 更多NUMA友好:
void saxpy_tasks(float* x, float* y, float a, int N) {
#pragma omp parallel
{
#pragma omp for
for (int i = 0; i < N; i++)
#pragma omp task
{
y[i] = y[i]+a*x[i];
}
}
}
在这种情况下,任务创建循环将在线程之间共享。
如果您不知道NUMA是什么,请忽略有关NUMA友好的评论。