【问题标题】:Max Reduction Open MP 2.0 Visual Studio 2013 C/C++最大缩减 Open MP 2.0 Visual Studio 2013 C/C++
【发布时间】:2015-08-25 22:34:56
【问题描述】:

我是新来的,这是我在这个网站上的第一个问题;

我正在做一个简单的程序来找到向量 c 的最大值,它是另外两个向量 a 和 b 的函数。我在 Microsoft Visual Studio 2013 上执行此操作,问题是它仅支持 OpenMP 2.0,我无法执行归约操作来直接找到向量的最大值或最小值,因为 OpenMP 2.0 不支持此操作。 我正在尝试使用以下代码在不减少构造函数的情况下进行:

for (i = 0; i < NUM_THREADS; i++){
    cMaxParcial[i] = - FLT_MAX;
}

omp_set_num_threads(NUM_THREADS);
#pragma omp parallel for private (i,j,indice)
for (i = 0; i < N; i++){
    for (j = 0; j < N; j++){
        indice = omp_get_thread_num();

        if (c[i*N + j] > cMaxParcial[indice]){
            cMaxParcial[indice] = c[i*N + j];
            bMaxParcial[indice] = b[j];
            aMaxParcial[indice] = a[i];
        }
    }
}
cMax = -FLT_MAX;

for (i = 0; i < NUM_THREADS; i++){
    if (cMaxParcial[i]>cMax){
        cMax = cMaxParcial[i];
        bMax = bMaxParcial[i];
        aMax = aMaxParcial[i];
    }

}

我收到错误消息:“表达式必须具有整数或无范围枚举类型” 在命令cMaxParcial[indice] = c[i*N + j];

谁能帮我解决这个错误?

【问题讨论】:

  • 你能发一个完整的minimal reproducible example吗?
  • 嗨,我犯了一个错误:我将 'indice' 声明为 float 而不是 int,现在我更正它并运行代码。但是我使用静态向量造成了错误共享,我们的同事帮助我发送了您的代码,例如示例。感谢您的评论

标签: c++ visual-studio visual-studio-2012 openmp


【解决方案1】:

通常,错误是由索引之一不是整数类型引起的。由于您没有显示声明 ijNindice 的代码,我的猜测是 Nindice 是浮点数或双精度数,但它会更简单回答您是否提供了MCVE。但是,它上面的行似乎正确使用了相同的索引。这让我相信这是一个 IntelliSense 错误,通常是误报。尝试编译代码并运行它。

现在,谈谈您(尚未)询问的问题(为什么我的并行代码比串行代码慢?)。您通过使用(可能)连续数组来查找每个线程的 a、b 和 c 值来导致 false sharing。不要将pragma 用于parallelfor,而是将其拆分如下:

cMax = -FLT_MAX;

#pragma omp parallel
{
    float aMaxParcialPerThread;
    float bMaxParcialPerThread;
    float cMaxParcialPerThread;

    #pragma omp for nowait private (i,j)
    for (i = 0; i < N; i++) {
        for (j = 0; j < N; j++) {
            if (c[i*N + j] > cMaxParcialPerThread){
                cMaxParcialPerThread = c[i*N + j];
                bMaxParcialPerThread = b[j];
                aMaxParcialPerThread = a[i];
            } // if
        } // for j
    } // for i
    #pragma omp critical 
        {
            if (cMaxParcialPerThread < cMax) {
                cMax = cMaxParcialPerThread;
                bMax = bMaxParcialPerThread;
                aMax = aMaxParcialPerThread;
            }
        }
}

【讨论】:

  • 您好 Avi Ginsburg,问题正是您所说的:我将变量“indice”声明为浮点数而不是整数。我在代码上更正了它,它可以工作!
  • 我是 Open MP 和一般并行编程的初学者,我像你说的那样在我的代码中使用静态向量造成了错误共享。我现在正在学习它,你的代码对于提高我的知识非常有用和重要。非常感谢您的评论和代码。
  • @PauloPaiva 欢迎来到 StackOverflow。我很高兴我能提供帮助。如果其中一个答案解决了您的问题或对您的帮助最大,则适当的操作是将其标记为已接受。见What should I do when someone answers my question?
【解决方案2】:

我不知道您的编译器出了什么问题,因为(据我所知,只有您提供的部分数据),代码似乎有效。但是,它有点令人费解,而且不太好。

下面的呢:

#include <omp.h>
#include <float.h>

extern int N, NUM_THREADS;
extern float aMax, bMax, cMax, *a, *b, *c;

int foo() {
    cMax = -FLT_MAX;
    #pragma omp parallel num_threads( NUM_THREADS )
    {
        float localAMax, localBMax, localCMax = -FLT_MAX;
        #pragma omp for
        for ( int i = 0; i < N; i++ ) {
            for ( int j = 0; j < N; j++ ) {
                float pivot = c[i*N + j];
                if ( pivot > localCMax ) {
                    localAMax = a[i];
                    localBMax = b[j];
                    localCMax = pivot;
                }
            }
        }
        #pragma omp critical
        {
             if ( localCMax > cMax ) {
                 aMax = localAMax;
                 bMax = localBMax;
                 cMax = localCMax;
             }
        }
    }
}

它可以编译,但我还没有测试过... 无论如何,我避免使用[a-c]MaxParcial 数组,因为它们会在线程之间产生错误的共享,从而导致性能下降。最后的缩减是基于critical 完成的。这并不理想,但只要您拥有“适度”数量的线程,它就会完美地执行。如果您在那里看到一些热点或者您需要使用“大量”线程,则可以稍后通过适当的并行减少来更好地优化它。

【讨论】:

  • 感谢您的建议。我会测试你的代码。我的代码的问题是我将 indice 声明为 float 而不是 int。但是我使用静态向量造成了错误共享,您的代码帮助我成为一个更好的程序员。
猜你喜欢
  • 2019-04-17
  • 1970-01-01
  • 2013-12-27
  • 2015-11-16
  • 1970-01-01
  • 2015-02-01
  • 2016-02-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多