首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么在C++中向后迭代数组比向前迭代快

为什么在C++中向后迭代数组比向前迭代快
EN

Stack Overflow用户
提问于 2018-10-16 18:40:37
回答 2查看 1.4K关注 0票数 4

我正在为一次考试做准备,并试图解决这个问题:我有下面的C代码来做一些数组初始化:

代码语言:javascript
运行
复制
int i, n = 61440;
double x[n];
for(i=0; i < n; i++) {
  x[i] = 1;
}

但是下面的运行速度更快( 1000次迭代相差0.5s):

代码语言:javascript
运行
复制
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,尽管在本例中,它都运行在一个内核上,代码中没有任何OpenMP指令)

代码语言:javascript
运行
复制
#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倍

Edit3:最小示例-上面描述的所有更改都本地化到向量更新方法。这是默认的向前版本,它比向后版本for(i = limit - 1; i >= 0; i--)耗时更长

代码语言:javascript
运行
复制
#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:采用AMD四核Opteron8378。这台机器使用了其中的4个,但我在主处理器上只使用了一个( AMD架构中的核心ID为0)

EN

回答 2

Stack Overflow用户

发布于 2018-10-16 19:23:50

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

代码语言:javascript
运行
复制
for(i=n-1; i >= 0; i--) {

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

票数 1
EN

Stack Overflow用户

发布于 2018-10-16 21:19:48

主要原因是你的编译器在优化方面不是很好。从理论上讲,一个更好的编译器没有理由不将两个版本的代码转换成完全相同的机器代码,而不是让其中一个变得更慢。

除此之外的一切都取决于结果机器代码是什么,以及它是在什么上运行的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52833586

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档