求解释,为何两种方式访问数组的运行效率完全相同

cfvmario 2011-07-19 04:07:02

int x[100];
int dummy(int i)
{
return i/2;
}

int _tmain(int argc, _TCHAR* argv[])
{
clock_t start, finish;
int z;
char c;

srand(1);
for(int i=0; i<10; i++)
for(int j=0; j<10; j++)
x[i*10+j]=rand();
// 第一种方式访问数组
srand(1);
start = clock();
for (int i=0; i<LOOPS; i++)
{
for(int j=0; j<10; j++)
for(int k=0; k<10; k++)
z=dummy(x[j*10+k]);
}
finish = clock();
cout << (finish-start) << endl;
// 第二种方式访问数组
srand(1);
start = clock();
for (int i=0; i<LOOPS; i++)
{
int *p=x;
for(int j=0; j<10; j++)
for(int k=0; k<10; k++)
{
z=dummy(*p);
p++;
}
}
finish = clock();
cout << (finish-start) << endl;

return 0;
}

直觉第二种应该比第一种要快才对,不是说指针自增要比算乘法下标快么。为什么输出结果发现几乎总是一样的,效率上没有区别
...全文
129 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
Ace丶双鱼 2011-07-19
  • 打赏
  • 举报
回复
Alt+8
  • 打赏
  • 举报
回复
呃。。。。少了个i++,
晨星 2011-07-19
  • 打赏
  • 举报
回复
我把你的程序改了一下,把z不断累加,而且最后要把结果打印出来,而不是用都不用。在g++中启用-O2优化选项,是有区别的,前面的比后面的慢27%。
#include<stdlib.h>
#include <iostream>
using namespace std;

int x[1000000;
int dummy(int i)
{
return i/2;
}

int main(int argc, char* argv[])
{
clock_t start, finish;
int z;
char c;

const int LOOPS = 1000;

srand(1);
for(int i=0; i<LOOPS; i++)
for(int j=0; j<LOOPS; j++)
x[i*LOOPS+j]=rand();


z = 0;
start = clock();
for (int i=0; i<LOOPS; i++)
{
for(int j=0; j<LOOPS; j++)
for(int k=0; k<LOOPS; k++)
z += dummy(x[j*LOOPS+k]);
}
finish = clock();
cout << "Z = " << z << endl;
cout << (finish-start) << endl;

z = 0;
start = clock();
for (int i=0; i<LOOPS; i++)
{
int *p=x;
for(int j=0; j<LOOPS; j++)
for(int k=0; k<LOOPS; k++)
{
z += dummy(*p);
p++;
}
}
finish = clock();
cout << "Z = " << z << endl;
cout << (finish-start) << endl;

return 0;
}
  • 打赏
  • 举报
回复

#include <stdio.h>
#define N 10000

int data[N];

void fun1()
{
int i;
int temp;

for (i = 0; i < N; i++)
{
temp = data[i] * 2;
}
}
void fun2()
{
int *p = data;
int i = 0;
int temp;

while(i < N)
{
temp = *p * 2;
p++;
}
}

void main()
{
fun1();
fun2();
}

对应的汇编:

TITLE bmp.c
.386P
include listing.inc
if @Version gt 510
.model FLAT
else
_TEXT SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT ENDS
_DATA SEGMENT DWORD USE32 PUBLIC 'DATA'
_DATA ENDS
CONST SEGMENT DWORD USE32 PUBLIC 'CONST'
CONST ENDS
_BSS SEGMENT DWORD USE32 PUBLIC 'BSS'
_BSS ENDS
_TLS SEGMENT DWORD USE32 PUBLIC 'TLS'
_TLS ENDS
FLAT GROUP _DATA, CONST, _BSS
ASSUME CS: FLAT, DS: FLAT, SS: FLAT
endif
_DATA SEGMENT
COMM _data:DWORD:02710H
_DATA ENDS
PUBLIC _fun1
_TEXT SEGMENT
_i$ = -8
_temp$ = -4
;----------------------------------------------fun1 start
_fun1 PROC NEAR
; File bmp.c
; Line 7
push ebp
mov ebp, esp
sub esp, 8
; Line 11
mov DWORD PTR _i$[ebp], 0
jmp SHORT $L339
$L340:
mov eax, DWORD PTR _i$[ebp]
add eax, 1
mov DWORD PTR _i$[ebp], eax
$L339:
cmp DWORD PTR _i$[ebp], 10000 ; 00002710H
jge SHORT $L341
; Line 13
mov ecx, DWORD PTR _i$[ebp]
mov edx, DWORD PTR _data[ecx*4]
shl edx, 1
mov DWORD PTR _temp$[ebp], edx
; Line 14
jmp SHORT $L340
$L341:
; Line 15
mov esp, ebp
pop ebp
ret 0
_fun1 ENDP
;----------------------------------------------fun1 end
_TEXT ENDS
;----------------------------------------------fun2 start
PUBLIC _fun2
_TEXT SEGMENT
_p$ = -4
_i$ = -12
_temp$ = -8
_fun2 PROC NEAR
; Line 17
push ebp
mov ebp, esp
sub esp, 12 ; 0000000cH
; Line 18
mov DWORD PTR _p$[ebp], OFFSET FLAT:_data
; Line 19
mov DWORD PTR _i$[ebp], 0
$L348:
; Line 22
cmp DWORD PTR _i$[ebp], 10000 ; 00002710H
jge SHORT $L349
; Line 24
mov eax, DWORD PTR _p$[ebp]
mov ecx, DWORD PTR [eax]
shl ecx, 1
mov DWORD PTR _temp$[ebp], ecx
; Line 25
mov edx, DWORD PTR _p$[ebp]
add edx, 4
mov DWORD PTR _p$[ebp], edx
; Line 26
jmp SHORT $L348
$L349:
; Line 27
mov esp, ebp
pop ebp
ret 0
_fun2 ENDP
;----------------------------------------------fun2 end
_TEXT ENDS
PUBLIC _main
_TEXT SEGMENT
_main PROC NEAR
; Line 30
push ebp
mov ebp, esp
; Line 31
call _fun1
; Line 32
call _fun2
; Line 33
pop ebp
ret 0
_main ENDP
_TEXT ENDS
END



china_ssl 2011-07-19
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 fengzhw 的回复:]

引用楼主 cfvmario 的回复:
C/C++ code

int x[100];
int dummy(int i)
{
return i/2;
}

int _tmain(int argc, _TCHAR* argv[])
{
clock_t start, finish;
int z;
char c;

srand(1);
for(int i=0; i<10;……
[/Quote]
而方法二会涉及函数调用开销,降低效率;
请问,是什么函数调用开销呢,我看除了一个是用指针表示地址,一个用乘法算出数组下标没有其它不同了啊。
china_ssl 2011-07-19
  • 打赏
  • 举报
回复
噢,谢谢楼主解释了。
fengzhw 2011-07-19
  • 打赏
  • 举报
回复
[Quote=引用楼主 cfvmario 的回复:]
C/C++ code

int x[100];
int dummy(int i)
{
return i/2;
}

int _tmain(int argc, _TCHAR* argv[])
{
clock_t start, finish;
int z;
char c;

srand(1);
for(int i=0; i<10; i++)
……
[/Quote]

以现在CPU的速度,简单代码要反复调用上千次甚至更多才能看出速度差异;

另外,编译器的优化技术可能会改写循环,影响你对代码效率的分析,最终要以汇编结果为准。
(更复杂的CACHE命中/回写等问题就不展开了,但是追求效率极致的时候,这个必须考虑)

你的代码,我大致看了一下,方法一可能涉及编译器的优化,提升效率;
而方法二会涉及函数调用开销,降低效率;

所以两个算法很难说哪个会更快。

看汇编代码
cfvmario 2011-07-19
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 china_ssl 的回复:]

引用楼主 cfvmario 的回复:
C/C++ code

int x[100];
int dummy(int i)
{
return i/2;
}

int _tmain(int argc, _TCHAR* argv[])
{
clock_t start, finish;
int z;
char c;

srand(1);
for(int i=0; i<10;……
[/Quote]
我们的原始代码就是以2维的方式,那里的2维是有物理意义的不能降为1维。所以也只能用2维的模拟程序测
china_ssl 2011-07-19
  • 打赏
  • 举报
回复
上面写错了是:

for(int j=0; j<100; j++){
z=dummy(*p);
p++;
}

难道是两个循环会效率高点求解释。
china_ssl 2011-07-19
  • 打赏
  • 举报
回复
[Quote=引用楼主 cfvmario 的回复:]
C/C++ code

int x[100];
int dummy(int i)
{
return i/2;
}

int _tmain(int argc, _TCHAR* argv[])
{
clock_t start, finish;
int z;
char c;

srand(1);
for(int i=0; i<10; i++)
……
[/Quote]

我不明白楼主怎么不

for(int j=0; j<99; j++){
z=dummy(*p);
p++;
}
至善者善之敌 2011-07-19
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 luciferisnotsatan 的回复:]
反汇编,看看编译出的代码有没有差异
[/Quote]

+++1release下看看汇编就知道了
luciferisnotsatan 2011-07-19
  • 打赏
  • 举报
回复
反汇编,看看编译出的代码有没有差异
赵4老师 2011-07-19
  • 打赏
  • 举报
回复
VC调试时按Alt+8,TC或BC用TD调试,打开汇编窗口看每句C对应的汇编并单步执行一遍不就啥都明白了吗。
(Linux或Unix下应该也可以在用GDB调试时,看每句C对应的汇编并单步执行。)
晨星 2011-07-19
  • 打赏
  • 举报
回复
另外,打开编译器优化选项后,发现还是没啥区别。
我觉得那个变量“z”根本没有被使用过,对它的计算完全可能被编译器整个给优化掉。
晨星 2011-07-19
  • 打赏
  • 举报
回复
偶在Linux上试你的程序,把数据量改成100万,还是有差别的,但不大。
cfvmario 2011-07-19
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 abao623660072 的回复:]
这样看效率,基本上没区别,要程序很大才会有.
[/Quote]
LOOPS已经定义成大常数让他反复运行了,还是没区别
看到我们很多代码都是第一种方式写的,脑子里首先想到的就是用第二种方式优化,但是一写这么个小程序测试发现没区别就不知道为什么了
金刚葫芦娃 2011-07-19
  • 打赏
  • 举报
回复
这样看效率,基本上没区别,要程序很大才会有.

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧