在循环后面声明变量还是在循环里面声明变量? - 页 5

 
pivalexander:

我更喜欢将代码分为逻辑块,并在其中声明所需的变量,而不是在一个函数的开头创建一堆变量,其中大部分只在一个块中需要,在下面很远的地方。

对于只在一个地方需要的变量--是的,在块本身之前声明它们是有意义的,特别是当块很小的时候。但是,如果块足够大,并且在其他地方需要变量--我宁愿在函数的开头声明它们。不过,你必须在这里使用常识。

 
pivalexander:

用空的循环体执行的结果是非常不同的,要快得多

Test1, время выполнения: 0.548275 сек.
Test2, Время выполнения: 0.313978 сек.

你用微秒来衡量什么?....你确定你有一个现实的测试吗?

;)

这里还有一个这样的测试。

#define  N 8

#define    test(M,S,EX,res) {                             \
uint mss=GetTickCount();                                 \
ulong nn=(ulong)pow(10,M);                               \
for(ulong tst=0;tst<nn && !_StopFlag;tst++) \
{ EX;  res }                                             \
printf("%s: loops=%i ms=%u",S,nn,GetTickCount()-mss);}
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   string result;
   string s1;  test(N,"1. s1=",s1=(string)tst, result = s1;);
   string s2;  test(N,"2. s2=",s2=(string)tst, result = s2;);
   string s3;  test(N,"3. s3=",s3=(string)tst, result = s3;);
   string s4;  test(N,"4. s4=",s4=(string)tst, result = s4;);
   string s5;  test(N,"5. s5=",s5=(string)tst, result = s5;);

   test(N,"1. q=",string q=(string)tst, result = q;);
   test(N,"2. w=",string w=(string)tst, result = w;);
   test(N,"3. e=",string e=(string)tst, result = e;);
   test(N,"4. r=",string r=(string)tst, result = r;);
   test(N,"5. t=",string t=(string)tst, result = t;);
  }

2019.08.18 12:14:20.765 SpeedTest (EURUSD,H1) 1. s1=: loops=100000000 ms=8156

2019.08.18 12:14:29.127 SpeedTest (EURUSD,H1) 2. s2=: loops=100000000 ms=8359

2019.08.18 12:14:37.353 SpeedTest (EURUSD,H1) 3. s3=: loops=100000000 ms=8235

2019.08.18 12:14:45.464 SpeedTest (EURUSD,H1) 4. s4=: loops=100000000 ms=8109

2019.08.18 12:14:53.557 SpeedTest (EURUSD,H1) 5. s5=: loops=100000000 ms=8094

2019.08.18 12:15:01.446 SpeedTest (EURUSD,H1) 1. q=: loops=100000000 ms=7890

2019.08.18 12:15:09.159 SpeedTest (EURUSD,H1) 2. w=: loops=100000000 ms=7703

2019.08.18 12:15:16.903 SpeedTest (EURUSD,H1) 3. e=: loops=100000000 ms=7750

2019.08.18 12:15:24.716 SpeedTest (EURUSD,H1) 4. r=: loops=100000000 ms=7813

2019.08.18 12:15:32.661 SpeedTest (EURUSD,H1) 5. t=: loops=100000000 ms=7937

 
Igor Makanu:

你用微秒来衡量什么?....你确定你的测试与现实相符吗?

   ulong  time_finish = GetMicrosecondCount();
   ulong  res = time_finish - time_start;

我就是这样衡量的。

 
pivalexander:

我是这样测量的。

我明白,但你必须至少测量几秒钟的时间

Windows不是一个实时系统,不是吗? 而且后台任务也需要Windows的资源,所以你的测试是在系统定时器 和后台进程的不准确程度上进行的

我认为,至少5秒的测试至少是一些可靠的信息。

 
Igor Makanu:

我理解,但你至少需要测量几秒钟的时间

Windows不是一个实时系统,对吗? 后台任务也需要Windows的资源,所以你的测试是基于系统定时器和后台进程的不精确性

我认为,至少5秒钟的测试至少是一些可信的信息。

我分别测量了几秒钟,结果是一样的,为什么要等这么久才在这里公布结果呢?

 

总的来说,我决定做一个测试,但要100%正确,这样就没有什么被剪掉了。

void OnStart()
{
  int count= (int)10 e6;

  { 
    uint t= GetTickCount();
    int sum=0;
        
    for (int i=0; i<count; i++)
    {
       string st = (string)i;
       sum += st[rand()%10];
    }
    Print("Test1, время выполнения: ", GetTickCount()-t," ms,  sum=",sum);
  }
  
  {
    uint t = GetTickCount();
    int sum=0;
    string st = "";
    for (int i=0; i<count; i++)
    {
       st = (string)i;
       sum += st[rand()%10];
    }
    Print("Test2, время выполнения: ", GetTickCount()-t," ms,  sum=",sum);
  }
}

在非优化模式下,第二种变体确实更快,而在优化模式下,情况正好相反。同时,第二种变体,不知为何变得比优化前更慢了)

 
pivalexander:

每次做了几秒钟的测量,结果是一样的,为什么要等很久才在这里公布结果呢?

和几次相同的测试必须运行,因为有一个高概率的缓存操作在接下来的测试中得到,那可能出来的2个相同的测试与小的差异将被执行不同的 - 你没有看到相同的测试的差异?

这取决于你,正如我在上面写的,我不相信任何人,甚至Windows、处理器和我自己;)


阿列克谢-纳沃伊科夫

一般来说,我决定做一个测试,但100%正确,没有任何东西被剪掉。

虽然在非优化模式下,第二种变体确实更快,但在优化模式下,情况正好相反。而第二种方式,由于某些原因,变得比优化前更慢)

这不是事实,没有srand(),我告诉你,rand()被编译器优化得非常酷;)

并至少复制2次脚本文本--这样你就可以看到编译器撕掉了什么;)

 
pivalexander:

内存和处理器有什么关系? 这是关于优化,你是一个书本上的理论家)

如果你在推理中比方括号走得更远,了解编译器是如何工作的,以及它的优化是如何工作的,你会发现任何编译器的目的都是为了减少代码执行的时钟周期,并尽可能减少非顺序的内存访问。 因此,任何编译器的优化结果,如果存在的话,不用任何愚蠢的测试,你就会事先知道。这就像用测试来计算2+2=4一样......。

而关于书本理论家...这位理论家从87年开始写作,从EC1020和ZX Spectrum开始,写了不止一个编译器,为他的公司雇用了600多名程序员。

 
Aleksandr Matveev:

如果你在推理中比括号走得更远,了解编译器是如何工作的,以及它的优化是如何进行的,你就会发现,任何编译器的目的都是尽可能地减少代码执行的时钟周期,减少非顺序的内存访问,因此,你会预先知道任何编译器的优化结果,如果它存在,不需要任何愚蠢的测试。这就像用测试来计算2+2=4一样......。

而关于书本理论家...这位理论家从87年开始工作,当时他开始使用EU1020和ZX Spectrum,自己编写了几个编译器,并邀请600多名程序员到他的公司工作...

你们忙着看书,赞美自己,但他们没有说到问题的本质,只是在理论上跳舞......如果你读了这个,你就会明白......内存和CPU,CPU和内存,电源也用在那里......。

[删除]  
你知道吗,一个字符串可以有一个小的内部缓冲区,对于小的字符串,数据可以完整地放在那里。所以说,要加快大多数琐碎案件的速度。在摆弄抓取malloc()的时候,我注意到如果字符串短于大约15个字符,malloc根本就不会乱动。你的测试将如何...