【问题标题】:Simple Convert OpenMp Parallel for to c# Parallel for简单地将 OpenMp Parallel for 转换为 c# Parallel for
【发布时间】:2014-11-22 12:39:31
【问题描述】:

嗨,我正在将此 c++ ( openmp ) 并行转换为 c# 并行,但它说:

错误 1 ​​并非所有代码路径都返回类型为 lambda 表达式的值 'System.Func<int,System.Threading.Tasks.ParallelLoopState,int,int>'

这是我的代码:

c++

void floyd_warshall(int NumOfThreads) {
    int i, j, k;

    omp_set_num_threads(NumOfThreads);
    for (k = 0; k < n; ++k)
        #pragma omp parallel for private(i,j)
        for (i = 0; i < n; ++i)
            for (j = 0; j < n; ++j)
                /* If i and j are different nodes and if
                    the paths between i and k and between
                    k and j exist, do */
                if ((dist[i][k] * dist[k][j] != 0) && (i != j))
                    /* See if you can't get a shorter path
                        between i and j by interspacing
                        k somewhere along the current
                        path */
                    if ((dist[i][k] + dist[k][j] < dist[i][j]) || (dist[i][j] == 0))
                        dist[i][j] = dist[i][k] + dist[k][j];
}

c#

 void floyd_warshall(int NumOfThreads)
        {
            int  k;
            ParallelOptions pOp;
            pOp.MaxDegreeOfParallelism = NumOfThreads;

            for (k = 0; k < n; ++k)
             Parallel.For<int>(0, n, pOp , () => 0, (i, loop, j) =>
                 {   //  for (i = 0; i < n; ++i)
                     for (j = 0; j < n; ++j)
                         /* If i and j are different nodes and if
                             the paths between i and k and between
                             k and j exist, do */
                         if ((dist[i, k] * dist[k, j] != 0) && (i != j))
                             /* See if you can't get a shorter path
                                 between i and j by interspacing
                                 k somewhere along the current
                                 path */
                             if ((dist[i, k] + dist[k, j] < dist[i, j]) || (dist[i, j] == 0))
                                 dist[i, j] = dist[i, k] + dist[k, j];
                 }, (j) => 0);
        }

【问题讨论】:

    标签: c# c++ multithreading parallel-processing


    【解决方案1】:

    您可以使用Parallel.For 方法的更简单重载,该方法不需要您的委托具有返回值。

        var pOp = new ParallelOptions { MaxDegreeOfParallelism = NumOfThreads };
    
        for (int k = 0; k < n; ++k)
            Parallel.For(0, n, pOp, i =>
            {   //  for (i = 0; i < n; ++i)
                for (int j = 0; j < n; ++j)
                    /* If i and j are different nodes and if
                        the paths between i and k and between
                        k and j exist, do */
                    if ((dist[i, k] * dist[k, j] != 0) && (i != j))
                        /* See if you can't get a shorter path
                            between i and j by interspacing
                            k somewhere along the current
                            path */
                        if ((dist[i, k] + dist[k, j] < dist[i, j]) || (dist[i, j] == 0))
                            dist[i, j] = dist[i, k] + dist[k, j];
            });
    

    【讨论】:

    • j 是每个线程的私有变量,因为它是在in匿名函数中声明的。如果您在外部方法的开头声明它(就像您在 C++ 代码中所做的那样),它就不会是私有的。
    【解决方案2】:

    我遇到了和你一样的问题,并设法解决了。事实证明,我们的代码与 Parallel.For 做的事情非常相似。你可以从这个link 看到我的解决方案。最大的区别似乎是您使用值类型(int)进行线程本地存储,而我使用的是引用类型。

    第一个问题是您需要一个 return 语句。例如,就在这一行之前:

    }, (j) => 0);
    

    添加类似:

    return 0;
    

    您可能需要做的第二件事是替换这一行:

    }, (j) => 0);
    

    类似:

    }, (j) => j = 0);
    

    这是 Parallel.For 函数的第 5 个参数,每个线程在其工作完成后调用。如果您需要保持值不变,您也可以通过执行 j = j 之类的操作来执行 no op。但是,这会产生一个自分配警告,您必须使用#pragma 来禁用该警告。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-25
      • 1970-01-01
      • 2021-06-08
      • 1970-01-01
      • 2022-12-27
      • 2021-08-20
      相关资源
      最近更新 更多