c - 为什么在 C 中向后迭代数组比向前迭代快

标签 c arrays traversal

我正在为考试而学习,并试图解决这个问题:
我有以下 C 代码来做一些数组初始化:

int i, n = 61440;
double x[n];
for(i=0; i < n; i++) {
  x[i] = 1;
}

但以下运行速度更快(1000 次迭代中的差异为 0.5 秒):
int i, n = 61440;
double x[n];
for(i=n-1; i >= 0; i--) {
  x[i] = 1;
}

我首先认为这是由于访问 n 变量的循环,因此必须进行更多读取(如此处建议的,例如: Why is iterating through an array backwards faster than forwards )。但即使我将第一个循环中的 n 更改为硬编码值,反之亦然,将底部循环中的 0 移动到一个变量,性能仍然保持不变。我还尝试将循环更改为只完成一半的工作(从 0 到 < 30720,或从 n-1 到 >= 30720),以消除对 0 值的任何特殊处理,但底部循环仍然更快

我认为这是因为一些编译器优化?但是我查找生成的机器代码的所有内容都表明 < 和 >= 应该相等。

感谢您的任何提示或建议!谢谢!

编辑:Makefile,用于编译器详细信息(这是多线程练习的一部分,因此是 OpenMP,但对于这种情况,它全部运行在 1 个内核上,代码中没有任何 OpenMP 指令)
#CC = gcc

CC = /opt/rh/devtoolset-2/root/usr/bin/gcc
OMP_FLAG = -fopenmp
CFLAGS = -std=c99 -O2 -c ${OMP_FLAG}
LFLAGS = -lm

.SUFFIXES : .o .c

.c.o:
    ${CC} ${CFLAGS} -o $@ $*.c

sblas:sblas.o
    ${CC} ${OMP_FLAG} -o $@ $@.o ${LFLAGS}

Edit2:我用 n * 100 重新进行了实验,得到了相同的结果:
前进:~170s
向后:~120s
与之前的值 1.7s 和 1.2s 类似,只是乘以 100

编辑 3:最小示例 - 上面描述的所有更改都本地化为 vector 更新方法。这是默认的向前版本,比向后版本花费的时间更长 for(i = limit - 1; i >= 0; i--)
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <omp.h>

void vector_update(double a[], double b[], double x[], int limit);

/* SBLAS code */

void *main() {
    int n = 1024*60;
    int nsteps = 1000;
    int k;

    double a[n], b[n], x[n];

    double vec_update_start;
    double vec_update_time = 0; 

    for(k = 0; k < nsteps; k++) {
    // Loop over whole program to get reasonable execution time
    // (simulates a time-steping code)
        vec_update_start = omp_get_wtime();
        vector_update(a, b, x, n);
        vec_update_time = vec_update_time + (omp_get_wtime() - vec_update_start);
   }

    printf( "vector update time = %f seconds \n \n", vec_update_time);
}

void vector_update(double a[], double b[], double x[] ,int limit) {
    int i;
    for (i = 0; i < limit; i++ )  {
        x[i] = 0.0;
        a[i] = 3.142;
        b[i] = 3.142;
    }
}

Edit4:CPU 是 AMD 四核 Opteron 8378。机器使用了其中的 4 个,但我在主处理器上只使用了一个(AMD 架构中的核心 ID 0)

最佳答案

这不是反向迭代,而是与零的比较导致第二种情况下的循环运行得更快。

for(i=n-1; i >= 0; i--) {

与零的比较可以用一条汇编指令完成,而与任何其他数字的比较则需要多条指令。

关于c - 为什么在 C 中向后迭代数组比向前迭代快,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52833586/

相关文章:

arrays - 如何在多对象 JSON 数组中编码/编码来 self 的服务器的响应

c++ - 如何使用后序遍历打印排序数组?

c - 在分层树中构造叶子

c - 如何修复C中的 'Program terminated with signal SIGBUS, Bus error'

c - fgets函数C

javascript - 如何旋转 Canvas 矩形数组

javascript - 如何删除外部阵列?

c - 错误 C2102 : '&' requires l-value

java - 在 Java 和 C 上重现相同 HMAC MD5 的问题

algorithm - python : List all possible paths in graph represented by dictionary