【问题标题】:finding maximum in a 3d matrix在 3d 矩阵中找到最大值
【发布时间】:2012-01-13 21:27:05
【问题描述】:

我有 3 维 (n*m*k) 的矩阵。我试图通过在 k 维中搜索来确定每个 n 和 m 的最大数量。((我尝试为每个 n 和 m 找到 k 维中的最大数量)),最后我有一个 2d 矩阵(n * m )。我有以下代码,但它太慢了。是否有任何新代码或对当前代码的任何更改可以更快地完成此操作。

谢谢。

我的 c# 代码:注意:li 是 3 维矩阵,它们大于或等于零。

int[,] array2 = new int[n, m];   
int[,] array = new int[n, m];
 List<Array> li = new List<Array>();             
for(int k = 0; k <'not a specific value, change each time' ; k++)
   { 
     li.Add(array);
     %% changing array
   } %% so li will became a (n*m*k) matrix   

for (int i = 0; i < n; i++)
                for (int j = 0; j < m; j++)
                {
                    int ma = -2;
                    int d = 0;
                    while (d <= k)
                    {
                        ma = Math.Max(ma, Convert.ToInt32(li[d].GetValue(i, j)));
                        d++;
                    }
                    array2[i, j] = ma;
                }

【问题讨论】:

  • li 是什么值?
  • 发布所有变量以及它们是如何在您的代码中声明/定义的..您如何声明 3 dim 数组..?显示代码
  • li : List li = new List();
  • li.Add(array);其中 int[,] 数组 = new int[n, m];
  • 有什么理由不使用 3D 数组?

标签: c# 3d matrix max


【解决方案1】:

最大的性能问题是您使用Array 对象作为列表的元素。这使得使用GetValue 的每个元素访问都将值装箱,即分配一个新的小对象来保存元素值。

如果你替换,你的代码会运行得更快

List<Array> li = new List<Array>();

List<int[,]> li = new List<int[,]>();

ma = Math.Max(ma, Convert.ToInt32(li[d].GetValue(i, j)));

ma = Math.Max(ma, li[d][i, j];

由于事先不知道第 3 维,所以使用 3D 数组比较困难。

一种完全不同的方法是在构建列表li 时计算最大值。这将在两个方面有所帮助:1. 避免索引到数组列表和 2. 只要 mn 不太大,就可以提高局部性。也就是说:您正在使用的值在内存中更接近,更有可能在处理器缓存中。

【讨论】:

    【解决方案2】:

    这应该可以解决问题(即使它可能比你的方法慢一点):

    // put this at the top of your source file
    using System.Linq;
    
    // put this where you calculate the maxima
    for(int i = 0; i < array2.GetLength(0); ++i)
    for(int j = 0; j < array2.GetLength(1); ++j)
    {
        array2[i, j] = Convert.ToInt32(li.Max(x => x.GetValue(i, j)));
    }
    

    【讨论】:

    • 这些代码的作用相同,但正如您所说的那样它们速度较慢。有更快的代码吗?谢谢你的回答
    【解决方案3】:

    你可以像这样使用一个三维数组:

    int xRange = 10;
    int yRange = 10;
    int zRange = 10;
    
    int[, ,] matrix = new int[xRange, yRange, zRange];
    
    // set up some dummy values
    for (int x = 0; x < xRange; x++)
        for (int y = 0; y < yRange; y++)
            for (int z = 0; z < zRange; z++)
                matrix[x, y, z] = x * y * z;
    
    // calculate maximum values
    int[,] maxValues = new int[xRange, yRange];
    
    /* LINQ version of maximum calculation
    for (int x = 0; x < xRange; x++)
        for (int y = 0; y < yRange; y++)
            maxValues[x, y] = Enumerable.Range(0, zRange).Select(z => matrix[x, y, z]).Max();
    */
    
    // longhand version of maximum calculation
    for (int x = 0; x < xRange; x++)
        for (int y = 0; y < yRange; y++)
            for (int z = 0; z < zRange; z++)
                maxValues[x, y] = Math.Max(maxValues[x, y], matrix[x, y, z]);
    
    // display results
    for (int x = 0; x < xRange; x++)
    {
        for (int y = 0; y < yRange; y++)
            Console.Write("{0}\t", maxValues[x, y]);
        Console.WriteLine();
    }
    

    【讨论】:

      【解决方案4】:

      从算法的角度来看,没有更有效的方法来评估所有 k 的固定 n,m 的最大值。它将需要 O(n*m*k) 次操作。

      现在,提高性能的唯一方法是在实施中找到改进,尤其是在 3D 矩阵的存储方面。

      使用List&lt;Array&gt; 是一个需要改进的主要领域。您很容易出现装箱问题(将原始类型转换为对象)并进行不必要的函数调用。

      将您的 3D 矩阵简化为基元数组:

      int[] my3DArray = new int[n * m * l]; // Note I'm using l where you use k 
      

      现在使用以下偏移量在 [i, j, k] 处索引您的数组:

      int elementAtIJK = my3DArray[i + (n * j) + (m * n * k)];
      

      如果您只使用基元数组,您应该会看到明显的改进。

      编辑:

      事实上,在 C#(和其他几种语言)中,直接很容易实现 3D 数组,例如:

         int[,,] my3DArray = new int[n,m,l];
         int elementAtIJK = my3DArray[i,j,k];
      

      这比我最初描述的要简单得多(但归根结底是在内部翻译成一维形式)。

      如果第 3 维大小不同怎么办...

      现在,如果第 3 维的大小发生显着变化,它会变得更有趣。如果它有一个已知的最大值并且不是太大,您可以简单地将其设置为最大值并用零填充空值。这很简单,可能会满足您的需求。

      但是,如果第 3 维可能非常大,所有这些额外存储的零可能会浪费大量宝贵空间,您需要的是 Sparse Matrix 表示。

      稀疏矩阵有不同的存储机制。出于您的目的,您可以将 3D 数组视为具有 (n*m) 行和 max(k) 列的 2D 矩阵。由于第 3 个维度的长度不同,因此您的列中有很多空格。这称为稀疏行,其标准数据存储为“压缩稀疏行”。同样,为了性能,这可以仅由三个原始数组表示,一个数据数组、一个行索引数组和一个列指针数组。网络上其他地方的资源比我更好地描述了 CSR 实施,但希望这会为您指明正确的方向。

      【讨论】:

      • 您也可以使用真正的 3 维数组(C# 支持)。性能只会变得更好,索引更容易(因此更不容易出错);)
      • 我知道 m , n 但我不知道 l 的大小。它取决于很多事情。那么我如何声明 my3DArray. ??
      • 当我声明数组时,它说它需要数组大小或数组初始值设定项。什么是数组初始值设定项。获得第三维的大值是个好主意吗??
      • 您的选择是将 k 维度设置为最大 k 可以(并用零填充)或使用稀疏矩阵实现。我已经用更多信息更新了我的答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-11-20
      • 2015-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-27
      相关资源
      最近更新 更多