【问题标题】:Is it possible to have a constant number in a spacial column of 2D array?二维数组的空间列中是否可以有一个常数?
【发布时间】:2014-09-28 19:14:27
【问题描述】:

我正在尝试改进代码的主要部分中的并行性。这个循环有主要的计算,每次输出需要做超过 100 万次(我需要 8000 万次输出)。因此,即使是轻微的改进,也会对执行时间产生严重影响。 我知道 IF 条件会降低并行计算速度。另外,我知道特殊位置的主要变量(U[i,j] 和 V[i,j])可能始终为零。因此,如果我可以为这些数组的特殊列分配常数零(不想改变计算),我可以从代码中消除 IF 条件。

Before calculation:
| 1 1 1 0 1|
| 1 1 1 0 1|
| 1 1 1 0 1|
| 1 1 1 0 1|
After calculation:
| 3 1 8 0 5|
| 1 4 4 0 1|
| 7 3 1 0 8|
| 1 1 5 0 7|

我想要一个其值始终为零的列。

如何为二维数组的空间列分配常数(零)?

作为示例,上述部分如下所示:

double[,] U= new double[nx,ny];
double[,] V= new double[nx,ny];

Parallel.For(0,nx,i =>
{
   For (j=0; j<ny ; j++)
   {
     if (i!=a && i!=b &&i!=c &&i!=d &&)
     {
       U[i,j]= ...; // A big chunk of calculations
       V[i,j]=... ;// A big chunk of calculations
     }
  }
}

有趣的是,当我运行代码时,我发现它使用了几乎 20% 的内核。是因为我的并行循环较弱还是我应该手动分配循环使用的核心数?

【问题讨论】:

  • 我已经编辑了你的标题。请参阅“Should questions include “tags” in their titles?”,其中的共识是“不,他们不应该”。
  • 参考地点?
  • 你听说过有特殊列的数组吗?
  • @JohnSaunders:我们可以为列分配常量值吗?
  • 好的,没有办法制作一个包含特殊列的数组。您必须更改算法以跳过您认为应该跳过的列。但是,我强烈建议您分析您的代码以找出时间花费在哪里。您很可能正在尝试解决错误的问题。特别是,您可能遇到线程争用问题,而不是花费过多 CPU 时间的问题。

标签: c# arrays optimization parallel.for


【解决方案1】:

这难道不是一点点改进吗?

Parallel.For(0,nx,i =>
{
   if (i!=a && i!=b &&i!=c &&i!=d &&)
   {
       For (j=0; j<ny ; j++)
       {
           U[i,j]= ...; // A big chunk of calculations
           V[i,j]=... ;// A big chunk of calculations
       }
   }
}

仅当i 不满足条件时才评估内部循环。否则,您实际上处于忙碌的等待状态。

【讨论】:

  • +1:我个白痴。这可能是也可能不是他的大问题,我肯定被数组中特殊列的想法所困扰,但是,嘿,i 在那个内部循环中是不变的,所以if 在那个内部循环中是不变的,所以,当然,把它从内部循环中拿出来!
  • @JohnSaunders 是的,我不确定这是否会有所帮助。我在想编译器可能已经在优化这个了。
  • 另外,我想知道 abcd 是 OP 想要排除的唯一索引吗?如果有一个更大的集合,那么可以想象Parallel.ForEach 带有一个返回索引值的迭代器可能会更好。不过,真正的答案是“个人资料、个人资料、个人资料”。
  • @JohnSaunders:你说得对。它没有帮助。但这是有趣的一点。谢谢
【解决方案2】:

在单独的内核中计算边界,因为只有它们有“if”子句。然后计算没有任何 if 条件的内部。预计 2 倍加速。

//interior (dont include borders)
Parallel.For(1,nx-1,i =>
{

       For (j=1; j<ny-1 ; j++)
       {
           U[i,j]= ...; // A big chunk of calculations
           V[i,j]=... ;// A big chunk of calculations
       } 

}

//exterior 1
Parallel.For(xx,xx1,i =>
{
   //another calculation
}

//exterior 2
Parallel.For(xx1,yy,i =>
{
   //another calculation
}

//exterior 3
Parallel.For(yy,yy1,i =>
{
   //another calculation
}

//exterior 4
Parallel.For(yy1,xx,i =>
{
   //another calculation
}

使用 C++ dll 进行内循环,甚至可以将 opencl 用于 gpgpu 的速度提高 10 倍(SIMD) --> 提高 30 倍。

【讨论】:

  • 问题是计算区域的异常点不在边界内。正如您熟悉物理概念一样,我在空腔中有一面墙,空腔的左侧和右侧有速度,但在墙区域内速度为零。因此,我的速度应该始终为零,但是在您的第一个 For 循环中,您计算​​壁面和壁面效应的速度不能在计算中显示。 heattransfer.asmedigitalcollection.asme.org/data/Journals/…
  • 你能解释一下如何在 C# 中使用 C++ dll 来获得更多的加速吗?
  • 在 C++ 中使用 dllexport 并在 c# 中使用具有正确 C 空间名称的 dllimport
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-23
  • 1970-01-01
  • 2021-11-16
  • 2021-08-01
相关资源
最近更新 更多