是时候获取位数组了

时间:2018-08-30 10:33:20

标签: c# arrays performance

在该代码中我有一个我不明白的问题:

ilProbekUcz= valuesUcz.Count; //valuesUcz is the list of <float[]>
for (int i = 0; i < ilWezlowDanych; i++) nodesValueArrayUcz[i] = new BitArray(ilProbekUcz);
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < ilProbekUcz; i++)
{
        int index = 0;
       linia = (float[])valuesUcz[i];//removing this line not solve problem
        for (int a = 0; a < ileRazem; a++)
                for (int b = 0; b < ileRazem; b++)
                        if (a != b)
                        {
                                bool value = linia[a] >= linia[b];
                                nodesValueArrayUcz[index][i] = value;
                                nodesValueArrayUcz[ilWezlowDanychP2 + index][i] = !value;
                                index++;
                        }
}
sw.Stop();

当我将valuesUcz的大小增加2倍时,执行时间将增加4倍

当我将valuesUcz的大小增加4倍时,执行时间将增加8倍 等等...

({ileRazemilWezlowDanych相同)

我了解:增加ilProbekUcz会增加BitArrays的大小,但是我对其进行了多次测试,这没问题-时间应该线性增长-在代码中:

ilProbekUcz= valuesUcz.Count; //valuesTest is the list of float[]
for (int i = 0; i < ilWezlowDanych; i++) nodesValueArrayUcz[i] = new BitArray(ilProbekUcz);
BitArray test1 = nodesValueArrayUcz[10];
BitArray test2 = nodesValueArrayUcz[20];
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < ilProbekUcz; i++)
{
        int index = 0;
       linia = (float[])valuesUcz[i];//removing this line not solve problem
        for (int a = 0; a < ileRazem; a++)
                for (int b = 0; b < ileRazem; b++)
                        if (a != b)
                        {
                                bool value = linia[a] >= linia[b];
                                test1[i] = value;
                                test2[i] = !value;
                                index++;
                        }
}

时间线性增长,所以问题是从数组中提取BitArray ...

有什么方法可以更快地做到这一点? (我想让时间线性增长)

1 个答案:

答案 0 :(得分:1)

您必须了解,测量时间有很多因素使他们不准确。如示例中所示,具有大数组时最大的因素是cashe misses。考虑到 cashe 时,编写同一件东西的速度通常可以快2-5倍甚至更多倍。这两个词非常粗略地说明了工作原理。缓存是cpu中的内存。它比ram快waaaaaaaaaaaaaaaay,因此,当您要从内存中获取变量时,需要确保此变量存储在缓存中而不是ram中。如果存储在缓存中,我们说我们有一个hit,否则是miss。有时,程序不是那么大,以至于它会将变量存储在硬盘中。在这种情况下,您在获取这些内容时会遇到huuuuuuuuuuuge的延迟!缓存示例:

假设我们在内存(ram)中有10个元素的数组

enter image description here

当您获得第一个元素testArray[0]时,因为 testArray [0] 不在缓存中,CPU会将此值以及带数字(请说3,该数字取决于数组的相邻元素的cpu),例如它存储到缓存testArray[0], testArray[1], testArray[2], testArray[3]

enter image description here

现在,当我们得到testArray[1]时,它在缓存中,因此我们有了hittestArray[2]testArray[3]相同。 testArray[4]不在缓存中,因此它与另外3个testArray[4]

一起获得testArray[5], testArray[6], testArray[7]

enter image description here

以此类推...
缓存misses的成本很高。这意味着您可能希望两倍大小的数组可以访问两倍的时间。但是这是错误的。更大的数组更多misses 并且时间可能会比您预期的增加2或3或4倍或更多倍。这是正常的。在您的示例中就是这样。从1亿个元素(第一个数组)开始,您将达到0亿个(第二个)。 misses不是两倍,而是您所看到的更多。一个非常酷的技巧与访问数组的方式有关。在您的示例中,ba1[j][i] = (j % 2) == 0;ba1[i][j] = (j % 2) == 0;差很多。 ba2[j][i] = (j % 2) == 0;ba1[i][j] = (j % 2) == 0;相同。你可以测试一下。只需反转i and j。这与2D数组在内存中的存储方式有关,因此在第二种情况下,您比第一种情况拥有更多的hits