首页
社区
课程
招聘
[旧帖] [求助]为何这种优化有效? 0.00雪花
发表于: 2009-12-22 13:09 1739

[旧帖] [求助]为何这种优化有效? 0.00雪花

2009-12-22 13:09
1739
无意之中看到这种优化
很不解...
忘各位大大给解释下..

#include "stdio.h"
#include "time.h"
void main()
{
        clock_t start;
        start = clock();
        long i =0;
        _asm
        {
         next:inc i
                 cmp i,100000000
                 jb next
        }
        printf("%d",clock()-start);
}
消耗机器时间  421

改成 下面的
#include "stdio.h"
#include "time.h"
void main()
{
        clock_t start;
        start = clock();
        long i =0;
        long j;
        _asm
        {
        next:inc i
                     mov j,0
        next1: inc j
                           cmp j,10000
                           jb next1
                           cmp i,10000
                           jb next
        }
        printf("%d",start-clock());
消耗机器时间: 328

这是为什么啊??

[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
免费 0
支持
分享
最新回复 (17)
雪    币: 21
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
猜测一下:
1,CPU超标量流水线处理技术。(时间并行与空间并行)

2,改进前:各指令具有数据相关性,几乎不能利用超标量流水线
   改进后:在每次i循环开始时,可以同时执行两条指令(两条流水线),即外层每一次循环时,inc i和mov j,0可以并行执行,于是节约了微小的时间。

3,大胆估计:约节约1000条指令的时间。

-------------参考:《计算机组成原理》-------------

坐等高手斧正。
2009-12-22 13:44
0
雪    币: 232
活跃值: (105)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
3
我也觉得
应该和多核CPU有关系..
不过只是猜测
还是等待大牛来核实一下~~
2009-12-22 19:55
0
雪    币: 724
活跃值: (81)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
楼主的测试方法可能有问题,有两方面影响楼主的测试结果:
  1.clock()获得的时间并不准确,它并不能精确到毫秒。
  2.测试程序会因线程切换而影响测试结果。
为了减少上述因素的影响,可以使用CPU内部时间标记,它基本上是CPU的时钟计数,并多次运行,可将程序修改如下:
void test()
{
  long i =0;
  long j;
  unsigned __int64 t1,t2,t3;
  __asm{
          rdtsc
          mov dword ptr t1,eax
          mov dword ptr t1+4,edx
  }
  _asm
  {
next:inc i
     cmp i,100000000
     jb next
  }
  __asm{
          rdtsc
          mov dword ptr t2,eax
          mov dword ptr t2+4,edx
  }
  i=0;
  _asm
  {
  next2:inc i
        mov j,0
  next3:inc j
        cmp j,10000
        jb next3
        cmp i,10000
        jb next2
  }
  __asm{
          rdtsc
          mov dword ptr t3,eax
          mov dword ptr t3+4,edx
  }
  t1=t2-t1;
  t2=t3-t2;
  printf("t1=%I64x,t2=%I64x\n",t1,t2);
}

void main()
{
    test();
    test();
    test();
    test();
    test();
    test();
}

请楼主再测一下,看结果如何?
2009-12-23 09:34
0
雪    币: 458
活跃值: (421)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
5
單線程的代碼流程 如何做到2條指令同是執行???
2009-12-23 17:22
0
雪    币: 458
活跃值: (421)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
6
OD反彙編之後的代碼  俺看不出是為什麼  關注中。。。。。。。
00401026  |> /FF45 FC       /INC DWORD PTR SS:[EBP-4]
00401029  |. |817D FC 00E1F>|CMP DWORD PTR SS:[EBP-4],5F5E100
00401030  |.^\72 F4         \JB SHORT 豆腐乾.00401026
00401032  |.  E8 8A000000   CALL 豆腐乾.004010C1
00401037  |.  2BC6          SUB EAX,ESI
00401039  |.  50            PUSH EAX
0040103A  |.  68 40704000   PUSH 豆腐乾.00407040                        ;  ASCII "First Time: %d
"
0040103F  |.  E8 4C000000   CALL 豆腐乾.00401090
00401044  |.  E8 78000000   CALL 豆腐乾.004010C1
00401049  |.  8BF0          MOV ESI,EAX
0040104B  |.  C745 FC 00000>MOV DWORD PTR SS:[EBP-4],0
00401052  |>  FF45 FC       /INC DWORD PTR SS:[EBP-4]
00401055  |.  C745 F8 00000>|MOV DWORD PTR SS:[EBP-8],0
0040105C  |>  FF45 F8       |INC DWORD PTR SS:[EBP-8]
0040105F  |.  817D F8 10270>|CMP DWORD PTR SS:[EBP-8],2710
00401066  |.^ 72 F4         |JB SHORT 豆腐乾.0040105C
00401068  |.  817D FC 10270>|CMP DWORD PTR SS:[EBP-4],2710
0040106F  |.^ 72 E1         \JB SHORT 豆腐乾.00401052
00401071  |.  E8 4B000000   CALL 豆腐乾.004010C1
00401076  |.  2BC6          SUB EAX,ESI
00401078  |.  50            PUSH EAX
00401079  |.  68 30704000   PUSH 豆腐乾.00407030                        ;  ASCII "Second Time:%d
"
0040107E  |.  E8 0D000000   CALL 豆腐乾.00401090
00401083  |.  83C4 10       ADD ESP,10
00401086  |.  5E            POP ESI
00401087  |.  8BE5          MOV ESP,EBP
00401089  |.  5D            POP EBP
0040108A  \.  C3            RETN
2009-12-23 17:33
0
雪    币: 21
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
1,一般的流水计算机只有一条指令流水线,所以称为标量流水计算机。所谓超标量流水,是指它具有两条以上的指令流水线。

2,如果不采用流水线,一条指令要 取指令-》指令译码-》执行运算-》结果写回;然后才能再取指令-》指令译码-》…… (一个时间一个动作)
   如果采用标量流水线的话,可流水执行一条指令(流水处理部件)。 (时间并行优势)
   如果是超标量流水(2条或更多),可以流水执行2条指令。 (空间并行优势)(参照3)

3,比如Pentium系统结构核心,其有两条指令流水线。假如是U和V两条指令流水线,每条流水线都有自己的ALU、地址生成电路、与数据cache的接口。这样的话,两条指令如果不是数据相关等,那么CPU就可以流水执行两条指令了。

建议参阅计算机组成原理相关书籍。
---------流水CPU技术---------

个人理解如此,可以探讨,我对这本帖也十分关注。这个效率提高,有点意思……

要期末考,计算机组成原理,汇编,网络…… ⊙﹏⊙b汗
2009-12-23 21:12
0
雪    币: 21
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
这个,我测了一下,不大明白。

这位看雪学长可否给指点下…………
2009-12-23 21:34
0
雪    币: 724
活跃值: (81)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
9
请楼上给出测试结果。
2009-12-23 22:41
0
雪    币: 391
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
10
直接用汇编代码当然编译更快
2009-12-23 22:44
0
雪    币: 724
活跃值: (81)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
11
再回8楼。
1.clock()函数并非从时钟硬件中获取时间,而是从系统的一个内存变量中取,该时间变量并非实时更新,间隔最长可能会到近20ms(依赖于系统)。
2.楼主的测试返回的时间已达数百ms,远远超过WINDOWS的线程调度时间间隔,也就是说楼主的每次测试中在两次执行clock()之间会发生许多次的线程调度,从而影响结果的准确性。因此,另外一种做法是缩小循环次数,如缩小为原来的1/100,则运行时间会小于线程调度间隔(但仍不能保证无线程切换)。我的测试结论与楼主相反,方法2比方法1慢11%左右
2009-12-24 10:39
0
雪    币: 21
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
这个学习了。

不过这样有个疑问:
1,楼主的测试方法确实可能会出现线程调度。(或者说一定出现了线程调度)
2,在您的测试方法中并没有解决掉线程调度这一问题,在两个rdstc之间还是会出现线程调度。(中间有循环,可能某次循环或某次指令后,CPU分配的时间片用完之后,就会发生线程调度)

混乱中。   继续关注。

疑问:到底这是不是个优化?

……………………坐等高手结贴。………………
2009-12-24 12:26
0
雪    币: 724
活跃值: (81)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
13
回楼上,我的方法确实没有解决线程调度问题, 所以我要多运行几次,以中和线程调度的影响(两段代码被打断的可能性是均等的),将循环次数减少到1/100,可以更好减小线程调度带来的影响。
    我在单核CPU和双核CPU测试的结论是方法2需要更长的时间,不是一种优化,等楼主的结论吧。
2009-12-24 12:57
0
雪    币: 285
活跃值: (16)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
14
一个是clock()-start  一个是start - clock()
2010-1-11 22:20
0
雪    币: 285
活跃值: (16)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
15
start - clock() 已经溢出了
2010-1-11 22:21
0
雪    币: 85
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
一个疑问:
如果抛开双核,多线程的话,方法2中
_asm
  {
        next:inc i
         mov j,0
        next1: inc j
         cmp j,10000
         jb next1
         cmp i,10000
         jb next
  }
仅mov j,0这一条语句就重复执行了10000次,相当比方法1无形中多出了10000条语句,试问怎么能快?
2010-1-11 22:39
0
雪    币: 724
活跃值: (81)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
17
呼吁楼主结贴!
2010-1-12 09:41
0
雪    币: 145
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
18
方法2: 相当于常说的循环展开,目前认为循环展开确实可以提高CPU的运算速度。至于在汇编中是不是像在高级语言里那样有效,这个有待商榷。
不过前面大家提到的时间精度问题,和线程调度确实会影响测试结果。
对这种情况应该是把循环运行很多次(例如100000次),然后统计来判断优化的效果。
2010-1-13 09:13
0
游客
登录 | 注册 方可回帖
返回
//