在C中:访问像2D数组一样使用的char*=malloc()比访问数组[]快吗?

在C中:访问像2D数组一样使用的char*=malloc()比访问数组[]快吗?,c,arrays,memory,optimization,C,Arrays,Memory,Optimization,刚刚无意中遇到了这个最近的问题: 我只是想知道:当我用一个简单的malloc创建一个2D数组并像我自己一样管理2D访问时: int row=100; int col=100; char* buffer = malloc(sizeof(char)*row*col); for(int i=0;i<row;i++){ for(int j=0;j<col;j++){ buffer[i*col+j]=128; } } int行=100; int col=1

刚刚无意中遇到了这个最近的问题:

我只是想知道:当我用一个简单的malloc创建一个2D数组并像我自己一样管理2D访问时:

int row=100;
int col=100;
char* buffer = malloc(sizeof(char)*row*col);
for(int i=0;i<row;i++){
    for(int j=0;j<col;j++){
        buffer[i*col+j]=128;
     }
}
int行=100;
int col=100;
char*buffer=malloc(sizeof(char)*行*col);
对于(inti=0;i来说,将动态内存分配的(小)开销留在一边,如果通过
[row][column]
*(row*rowsize+column)
访问内存区域中的特定元素,则没有什么区别。基本上,这只是表示法上的区别

因此,您的问题更像是“将数组定义为“行优先”比“列优先”好吗?”

答案是:只有您知道,因为您是根据应用程序的需要定义内存区域访问模式的人

除非处理非常大的数组(其中一个维度大于适合缓存的维度),否则对此我不会想太多。

将动态内存分配的(小)开销放在一边,如果通过
[row][column]
*访问内存区域中的特定元素,则没有什么区别(row*rowsize+column)
。这基本上只是符号上的差异

因此,您的问题更像是“将数组定义为“行优先”比“列优先”好吗?”

答案是:只有您知道,因为您是根据应用程序的需要定义内存区域访问模式的人


除非您处理非常大的阵列(其中一个维度大于适合缓存的维度),否则我不会对此考虑太多。

注1:

在第一个代码段中,数组在进程的堆上分配,而在第二个代码段中,您在堆栈上分配缓冲区。如果要使用较大的数组,可能会得到一个…stackoverflow:)

注2:

我的解释集中在您希望使用**(在您的例子中是int**)类型动态分配2D数组的情况

处理2D数组时,将其分配为1D数组并使用智能索引将其作为2D数组访问会更快。这是因为:

  • 1D数组填充内存中的一个连续空间(较低的碎片)。这可以更好地缓存数组,减少访问延迟
  • 分配2D数组时,您有另一个间接级别,这意味着您需要先获取行地址,然后访问元素。使用1D数组时,您直接访问元素
  • 当数组以1D方式分配时,很容易将其与缓存线大小对齐。这将使编译器更容易优化事务,并避免对位于缓存线边界上的元素进行2次读取
  • 处理1D数组,应该有助于编译器生成更好的矢量化代码

    • 注1:

      在第一个代码段中,数组在进程的堆上分配,而在第二个代码段中,您在堆栈上分配缓冲区。如果要使用较大的数组,可能会得到一个…stackoverflow:)

      注2:

      我的解释集中在您希望使用**(在您的例子中是int**)类型动态分配2D数组的情况

      处理2D数组时,将其分配为1D数组会更快,并使用智能索引将其作为2D数组访问。这是因为:

      • 1D数组填充内存中的连续空间(较低的碎片)。这样可以更好地缓存阵列,减少访问延迟
      • 当您分配一个2D数组时,您有另一个级别的间接寻址,这意味着您需要首先获取行的地址,然后访问元素。使用一维数组时,可以直接访问元素
      • 当以1D方式分配阵列时,很容易将其与缓存线大小对齐。这将使编译器更容易优化事务,并避免对位于缓存线边界上的元素进行2次读取
      • 处理1D数组,应该有助于编译器生成更好的矢量化代码

      在第一种情况下,使用int idx=i*col可能会获得更快的访问速度;对于(int j=0;jalso),索引应该是缓冲区[i*col+j]好的,谢谢你的评论,尽管关于顺序存取的速度优势的一般问题仍然存在。好吧,这将给我一个价值,但没有解释我关于为什么它更快的理论是否正确……知道哪个理论正确的唯一方法是在你的系统上试用。不同的条件可能会产生不同的结果。在第一种情况下,使用int-idx=i*col;for(int-j=0;jalso,索引应该是buffer[i*col+j]可以更快地访问好的,谢谢你的评论,尽管关于顺序存取的速度优势的一般问题仍然存在。好吧,这将给我一个价值,但没有解释我关于为什么它更快的理论是否正确……知道哪个理论正确的唯一方法是在你的系统上试用。不同的条件可能会产生不同的结果。谢谢!我没有料到访问特定元素会有多大的不同,但我想知道,如果像我在嵌套循环中那样按顺序访问所有元素,是否会有(通常可以解释的)差异。这个问题的意思更像“在行和列中定义数组更好,还是在一行中定义数组更好?”@mfro我认为这不是一个好的建议。由于我在文章中提到的原因,使用1D几乎总是更好。你同意1D使用更好的缓存,但使用1D也有更多的优势。行fi
      int row=100;
      int col=100;
      char buffer[row][col];
      for(int i=0;i<row;i++){
          for(int j=0;j<col;j++){
              buffer[i][j]=128;
           }
      }