C# 如何优化此嵌套for循环,其中多维数组索引查找的开销最大

C# 如何优化此嵌套for循环,其中多维数组索引查找的开销最大,c#,C#,比如说 for (int i=0;i<100;i++) for (int j=0;j<100;j++) for (int k=0;k<100;k++) for (int l=0;l<100;l++) for (int m=0;m<100;m++) { DoSth(myArray[i,j,k,l,m]); } for(int i=0;i简单地说:如果你能帮助,如果你真的需要速度,就不要使用多维数组。

比如说

 for (int i=0;i<100;i++)
   for (int j=0;j<100;j++)
     for (int k=0;k<100;k++)
       for (int l=0;l<100;l++)
         for (int m=0;m<100;m++)
  {
     DoSth(myArray[i,j,k,l,m]);
  }

for(int i=0;i简单地说:如果你能帮助,如果你真的需要速度,就不要使用多维数组。它们的访问速度比一维数组慢得多。我不知道“秩2”和“秩5”之间有多大区别,但是向量之间的区别(总是基于0的,一维)数组(任意基,可以是多维的)如果很大的话

看起来你是在按明显的顺序遍历整个数组,所以只需将其作为一个一维数组。请注意,这是一个包含40GB数据的
int
数组。你真的有那么多数据吗?数据是否都在物理内存中而不是交换

编辑:好的,现在您已经完全改变了问题……您可以从不在每次迭代中重新蚀刻
a[i]
b[j]
开始(这可能会产生严重的缓存影响):

for(int i=0;i<100;i++)
{
int ai=a[i];
对于(int j=0;j<100;j++)
{
int bj=b[j];
对于(int k=0;k<100;k++)
{
int ck=c[k];
对于(int l=0;l<100;l++)
{
dl=d[l];
对于(int m=0;m<100;m++)
{
int em=e[m];
剂量测定法(myArray[ai,bj,ck,dl,em]);
}
}
}
}
}

根据您的问题使用锯齿状数组也会有所帮助,但可能会对内存产生重大影响。另一种选择是使用一维数组,并计算出“基本索引”在循环的每一级。

简单地说:如果你能帮忙,如果你真的需要速度,就不要使用多维数组。它们的访问速度比一维数组慢得多。我不知道“秩2”和“秩5”之间有多大区别,但向量之间的区别是什么(始终是基于0的,一维)和数组(任意基,可以是多维的),如果非常大的话

看起来你是在按明显的顺序遍历整个数组,所以只需将其作为一个一维数组。请注意,这是一个包含40GB数据的
int
数组。你真的有那么多数据吗?数据是否都在物理内存中而不是交换

编辑:好的,现在您已经完全改变了问题……您可以从不在每次迭代中重新蚀刻
a[i]
b[j]
开始(这可能会产生严重的缓存影响):

for(int i=0;i<100;i++)
{
int ai=a[i];
对于(int j=0;j<100;j++)
{
int bj=b[j];
对于(int k=0;k<100;k++)
{
int ck=c[k];
对于(int l=0;l<100;l++)
{
dl=d[l];
对于(int m=0;m<100;m++)
{
int em=e[m];
剂量测定法(myArray[ai,bj,ck,dl,em]);
}
}
}
}
}
根据您的问题使用锯齿状数组也会有所帮助,但可能会对内存产生重大影响。另一种选择是使用一维数组,并在循环的每个级别计算“基本索引”。

可能是

foreach (int x in myArray) {
    DoSth(x);
}

正如Jon Skeet所说,你的数组是巨大的!如果它主要包含空值,你应该考虑另一种方法。你可以使用字典来存储值。

var dict = new Dictionary<long,int>();

if (value != 0) {
    long index = (((i * 100 + j) * 100 + k) * 100 + l) * 100 + m;
    dict[index] = value;
}

可能是


正如Jon Skeet所说,你的数组是巨大的!如果它主要包含空值,你应该考虑另一种方法。你可以使用字典来存储值。

var dict = new Dictionary<long,int>();

if (value != 0) {
    long index = (((i * 100 + j) * 100 + k) * 100 + l) * 100 + m;
    dict[index] = value;
}


如果数组是稀疏的(多个零),则以
元组
为键的字典速度会快得多:

var dict = new Dictionary<Tuple<int, int, int, int int>, int>();

// Add element
dict[new Tuple(i,j,k,l,m)] = value;

// Get element
value = dict[new Tuple(i,j,k,l,m)];

// Traverse
foreach(var kv in dict)
{
     // You can always get the indexes if you need to
     int i = kv.Key.Item1;
     int j = kv.Key.Item2;
     int k = kv.Key.Item3;
     int l = kv.Key.Item4;
     int m = kv.Key.Item5;

     // ...Or do something
     DoSomething(kv.Value);
}
var dict=newdictionary();
//添加元素
dict[新元组(i,j,k,l,m)]=值;
//获取元素
value=dict[新元组(i,j,k,l,m)];
//横穿
foreach(以dict为单位的var kv)
{
//如果需要,可以随时获取索引
int i=kv.Key.Item1;
int j=kv.Key.Item2;
int k=kv.Key.Item3;
int l=kv.Key.Item4;
int m=kv.Key.Item5;
//…或者做点什么
剂量测定法(千伏值);
}

如果您的数组是稀疏的(多个零),则使用
元组作为键的字典将更快:

var dict = new Dictionary<Tuple<int, int, int, int int>, int>();

// Add element
dict[new Tuple(i,j,k,l,m)] = value;

// Get element
value = dict[new Tuple(i,j,k,l,m)];

// Traverse
foreach(var kv in dict)
{
     // You can always get the indexes if you need to
     int i = kv.Key.Item1;
     int j = kv.Key.Item2;
     int k = kv.Key.Item3;
     int l = kv.Key.Item4;
     int m = kv.Key.Item5;

     // ...Or do something
     DoSomething(kv.Value);
}
var dict=newdictionary();
//添加元素
dict[新元组(i,j,k,l,m)]=值;
//获取元素
value=dict[新元组(i,j,k,l,m)];
//横穿
foreach(以dict为单位的var kv)
{
//如果需要,可以随时获取索引
int i=kv.Key.Item1;
int j=kv.Key.Item2;
int k=kv.Key.Item3;
int l=kv.Key.Item4;
int m=kv.Key.Item5;
//…或者做点什么
剂量测定法(千伏值);
}

给抖动一个优化的机会:

for (int i=0; i < myArray.GetLength(0);i++)
   for (int j=0; j < myArray.GetLength(1);j++)
     for (int k=0; k < myArray.GetLength(2);k++)
       for (int l=0; l < myArray.GetLength(3);l++)
         for (int m=0; m < myArray.GetLength(4);m++)
  {
     DoSth(myArray[i,j,k,l,m]);
  }
for(int i=0;i
这将比这种情况下加快锯齿阵列的速度

而且至少它更容易维护


真正的加速案例:

int[][][] myArray = ...; // create it
....


for (int i=0; i < myArray.Length; i++)
{
   subArray1 = myArray[i];
   for (int j=0; j < subArray1.Length; j++)
   {
     subArray2 = subArray2[j];
     for (int k=0; k < subArray2.Length; k++)
     {
        subArray2[k] = ...
     }
   }
}
int[]myArray=…;//创建它
....
for(int i=0;i
给抖动一个优化的机会:

for (int i=0; i < myArray.GetLength(0);i++)
   for (int j=0; j < myArray.GetLength(1);j++)
     for (int k=0; k < myArray.GetLength(2);k++)
       for (int l=0; l < myArray.GetLength(3);l++)
         for (int m=0; m < myArray.GetLength(4);m++)
  {
     DoSth(myArray[i,j,k,l,m]);
  }
for(int i=0;ifor (int i=0; i < myArray.GetLength(0);i++)
   for (int j=0; j < myArray.GetLength(1);j++)
     for (int k=0; k < myArray.GetLength(2);k++)
       for (int l=0; l < myArray.GetLength(3);l++)
         for (int m=0; m < myArray.GetLength(4);m++)
  {
     DoSth(myArray[i,j,k,l,m]);
  }
int[][][] myArray = ...; // create it
....


for (int i=0; i < myArray.Length; i++)
{
   subArray1 = myArray[i];
   for (int j=0; j < subArray1.Length; j++)
   {
     subArray2 = subArray2[j];
     for (int k=0; k < subArray2.Length; k++)
     {
        subArray2[k] = ...
     }
   }
}