另一个二维数组分配问题 c#

25 浏览
0 Comments

另一个二维数组分配问题 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();
        }
    }
}

0
0 Comments

另一个二维数组分配问题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];
        // 执行其他操作
    }
}

通过按行访问数组,可以确保每次内存读取都能充分利用,并减少对内存的多次访问。这将提高程序的性能和效率。

在处理二维数组分配问题时,正确的内存访问方式对于程序的性能至关重要。通过按行访问数组,我们可以充分利用内存的读取效率,提高程序的性能和效率。

0
0 Comments

另一个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 Comments

在这个问题中,出现的原因是缓存效应。一个二维数组在内存中的布局如下所示:

(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的缓存大小。

0