我有三维矩阵(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;
}
答案 0 :(得分: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.只要m
和n
不是太大,就可以改善地点。也就是说:您正在使用的值在内存中更紧密,并且更可能位于处理器缓存中。
答案 1 :(得分:0)
这应该可以解决问题(即使它可能比你的方法慢一些):
// 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)));
}
答案 2 :(得分:0)
从算法的角度来看,没有更有效的方法来评估所有k的固定n,m的最大值。这将需要O(n * m * k)操作。
现在,提高性能的唯一方法是在实现中找到改进,特别是在存储3D矩阵时。
使用List<Array>
是一个需要改进的主要方面。您很容易出现装箱问题(将原始类型转换为对象)以及进行比必要更多的函数调用。
将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];
这比我最初描述的要简单得多(但在一天结束时内部翻译为1D形式)。
如果第三维尺寸变化怎么办......
现在,如果第三维的大小变化很大,它会变得更有趣。如果它具有已知最大值并且不是太大,则可以将其设置为最大值并使用零填充空值。这很简单,可以满足您的需求。
但是,如果第三维可能非常大,那么所有这些额外存储的零可能会浪费大量宝贵的空间,您需要的是Sparse Matrix表示。
稀疏矩阵有不同的存储机制。出于您的目的,您可以将3D阵列视为2D矩阵,具有(n * m)行和max(k)列。由于第三维的长度不同,因此列中有很多空白区域。这称为稀疏行,标准数据存储为“压缩稀疏行”。同样,为了性能,这可以仅由三个原始数组,数据数组,行索引数组和列指针数组表示。网络上的其他资源可以比我更好地描述CSR实施,但希望这会指出您正确的方向。
答案 3 :(得分:0)
您可以使用这样的三维数组:
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();
}