另一个二维数组分配问题 c#
另一个二维数组分配问题 c#
我在试图弄清楚为什么“选择A”比“选择B”表现更好。我的测试结果显示大约是228比830,差距大约是4倍。从IL代码来看,没有经过训练的眼睛无法看出这两个调用之间的细微差别。\n谢谢,\nStephen\n我将其拆分为两个独立运行的部分,以减少任何缓存或诊断的影响... 无论如何,B总是落后于A。\n程序A:\n
namespace ConsoleApplication1 { class ProgramA { const int SIZE = 10000; static void Main(string[] args) { var sw = Stopwatch.StartNew(); int[,] A = new int[SIZE, SIZE]; int total, x, y; // 选择A total = 0; for (x = 0; x < SIZE; x++) { for (y = 0; y < SIZE; y++) { total += A[x, y]; } } Console.WriteLine(sw.ElapsedMilliseconds); Console.ReadLine(); } } }
\n程序B:\n
namespace ConsoleApplication1 { class ProgramB { const int SIZE = 10000; static void Main(string[] args) { var sw = Stopwatch.StartNew(); int[,] A = new int[SIZE, SIZE]; int total, x, y; // 选择B total = 0; for (y = 0; y < SIZE; y++) { for (x = 0; x < SIZE; x++) { total += A[x, y]; } } Console.WriteLine(sw.ElapsedMilliseconds); Console.ReadLine(); } } }
另一个二维数组分配问题C#
要进一步扩展缓存答案:
所涉及的值每个占用4个字节,如果我没记错的话,当前的内存架构会从内存中读取16字节的行,假设主板已经正确配置。(我不知道DDR3,它的三芯片结构表明读取的数据量更大。)因此,当你读取一行内存时,你会得到4个值。
当你采用第一种方式时,在回到内存获取下一行之前,你会使用完所有这些值。而采用第二种方式时,你只使用其中一个值,然后它会在被再次调用之前从芯片上的缓存中被清除。
问题的原因:
问题的原因是在分配二维数组时,使用了不同的内存访问方式。第一种方式一次性使用了一整行的内存值,而第二种方式只使用了一部分,并且在再次使用之前就将其清除。这导致了内存的低效利用,从而影响了程序的性能。
解决方法:
要解决这个问题,可以考虑重新分配二维数组的方式。可以修改代码,使其按照一次性使用一整行的方式进行内存访问,以充分利用内存的读取效率。下面是一个示例代码:
int[,] array = new int[rows, columns]; // 按行访问数组 for (int i = 0; i < rows; i++) { for (int j = 0; j < columns; j++) { // 使用数组值 int value = array[i, j]; // 执行其他操作 } }
通过按行访问数组,可以确保每次内存读取都能充分利用,并减少对内存的多次访问。这将提高程序的性能和效率。
在处理二维数组分配问题时,正确的内存访问方式对于程序的性能至关重要。通过按行访问数组,我们可以充分利用内存的读取效率,提高程序的性能和效率。
另一个2维数组分配问题 c#
如果将2维数组想象成内存中的一张表,第一个值是行,第二个值是列。
[0, 0] [0, 1] [0, 2] [0, 3]...
[1, 0] [1, 1] [1, 2] [1, 3]...
当你对其进行迭代时,第一个循环是行,第二个循环是列。通过对每一行进行迭代,为每一列赋值,可以更快地进行迭代。
在第二种情况下,它的值被分配为
[0, 0] [1, 0] [2, 0] [3, 0]...
[0, 1] [1, 1] [2, 1] [3, 1]...
所以这种方式较慢,因为你循环时,你是按照每一列,每一行进行赋值。你只为每一行分配第一列的值。
这样是否有意义?
编辑:这就是我正在寻找的其中一个原因:
http://en.wikipedia.org/wiki/Row-major_order
在行优先存储中,线性内存中的多维数组是这样访问的:按照行的顺序依次存储。
因此,当一次迭代一行时,它不会在内存中跳来跳去寻找每一行来为列分配值,它有了行,为所有列分配值,然后跳到内存中的下一行。
在这个问题中,出现的原因是缓存效应。一个二维数组在内存中的布局如下所示:
(0, 0) (0, 1) (0, 2) (0, 3) (1, 0) (1, 1) (1, 2) ...
在选项A中,您正在顺序访问内存中的连续元素-这意味着当CPU获取一个缓存行时,它会获取多个连续的元素。而选项B则在内存中跳来跳去。因此,一旦数组的大小超过缓存大小,选项B需要进行更多的内存访问。
然而,缓存的大小是由CPU决定的。也就是说,缓存的大小会因不同的CPU而异。例如,在我的CPU上,缓存大小为1MB时,选项B的执行时间是选项A的8倍(350 ms vs 2888 ms)。
为了解决这个问题,可以考虑使用一维数组来代替二维数组。这样可以使得数据在内存中的布局更连续,从而减少内存访问的次数。另外,还可以尝试调整数组的大小,使其适应特定CPU的缓存大小,以提高性能。
总之,这个问题的出现是由于缓存效应导致的内存访问次数增加。要解决这个问题,可以考虑使用一维数组替代二维数组,并调整数组大小以适应特定CPU的缓存大小。