向#define专家提问 - 页 6

 
Igor Makanu:

如果你在循环的主体中改变数组的大小,即时优化就不起作用了

所以要修改代码。

)))),只是你还必须改变你的尺寸变量的值,所以使用ArraySIze 的命名第一种方法将受益于

 
Alexandr Andreev:

好吧,我不能说什么反对IMHO。

在非常大的复赛中,我的胜利已经成为第一和第二种方法的随机性...最有可能的是,它变得依赖于当前的CPU缓存和整体负载。

我的问题不是关于循环的--而是关于函数如何展开的。只是,ArraySize被用作一个例子。

这很好)高级语言的完美之处正是当一个方便的条目和一个不方便但最初很便宜的条目一样便宜时。太糟糕了,并不总是这样,对新手的帮助也不总是这样,要么.....,就不会有问题)))

 
Igor Makanu:

如果你在循环的主体中改变数组的大小,即时优化就不起作用了

所以要改变代码。


不起作用

运行时优化处于领先地位

如果没有剖析器,你无法测试这样简单的mashin命令,或者你可以在循环中写,或者在测试器中测试,速度对它很重要。

我不是在谈论循环,而是在谈论编译器如何展开功能.....,来吧。

我让你去吧。

 
Alexandr Andreev:

)))),你也被允许改变你的尺寸变量的值,所以第一个使用ArraySIze的 方法将获胜

我在上面写道--这种简单的代码不能用简单的测量来测试,有很多因素--代码很小--它将适合处理器的缓存,代码必须在处理器中很好地分解成处理器流水线中的并行微命令,即寄存器将通过数据预取快速加载。

也许rand()也会被缓存在某个地方


好吧,我不知道在没有调试器的情况下如何测试 - 至少在那里你可以看到指令执行的时间。

 
Alexandr Andreev:

那就证明我错了)。

因为在我的测试中,出于某种原因,它们是一样的。

改了我的帖子。
在我看来,现在ArraySize 比cnt变量快。
早些时候,情况恰恰相反。也许增量cnt--会受到影响,循环体是不同的,可能必须发明其他的东西来加载。

void OnStart()
{
   int arr[];
   int sz = ArrayResize(arr, 100000000);  
   
   ulong t = GetMicrosecondCount();
   
   for(int i=0; i < ArraySize(arr); i++) 
   {
      ArrayResize(arr, sz--); //какая то нагрузка
   }   
   
   t = GetMicrosecondCount() - t;
   
   PrintFormat("Total time: %.3f ms", t / 1000.0);
}
2020.11.02 21:33:22.863 TestScript (USDJPY,M1)  Total time: 451.200 ms


void OnStart()
{
   int arr[];
   int sz = ArrayResize(arr, 100000000);  
   int cnt = ArraySize(arr);
   
   ulong t = GetMicrosecondCount();
   
   for(int i=0; i < cnt; i++) 
   {
      ArrayResize(arr, sz--);
      cnt--;
   }
      
   t = GetMicrosecondCount() - t;
   
   PrintFormat("Total time: %.3f ms", t / 1000.0);
}
2020.11.02 21:56:26.591 TestScript (USDJPY,M1)  Total time: 531.872 ms
 
Roman:

这很奇怪。
在循环条件中使用ArraySize(arr)显示的时间比使用cnt变量少。
以前是反之亦然。也许这是一个错误?它不应该是这样的。

你的代码中没有混入任何东西,谁会为你改变价值?

cnt

为你改变它,因为它发生在第一个变体中

 
void OnStart()
  {
   int mas[];
   int size=1000000;
   ArrayResize(mas,size);
   ulong r=0;
   ulong r1=0;
   ulong r2=0;
   int random;
   ulong max=100;
   uint t1=GetTickCount();
   int t=0;
   int tr=0; 
   MathSrand(10);
   for(ulong z=0; z<max; z++)
     {
      for(ulong i=0; i<ArraySize(mas); Funk(i))
        { 
         FunkRand(r1); 
         Funk(r);// мы сюда написали вызов еще одной функции чтобы усложить ситуацию
        }
     }
   tr=r;
   uint t2=GetTickCount();
   for(ulong z=0; z<max; z++)
     {
     int v=size;
      for(ulong i=0; i<v; i++)
        { 
         r2+=rand();
         r--;
        }

     }

   uint t3=GetTickCount();
   Print(t2-t1,"  ",t3-t2," ",r," ",r1," ",r2," ",t1," ",tr);
// Templ();
  }

//+------------------------------------------------------------------+
//|                                           
  
void Funk(ulong &a){a++;}
void FunkRand(ulong &a){a+=rand();}

//+------------------------------------------------------------------+

500p的问题(没有检查),哪种方式更快。看看在顶部方法中调用了多少外部函数

Документация по MQL5: Основы языка / Функции / Описание внешних функций
Документация по MQL5: Основы языка / Функции / Описание внешних функций
  • www.mql5.com
Внешние функции, определенные в другом модуле, должны быть явно описаны. Описание включает в себя тип возвращаемого значения, имя функции и набор входных параметров с их типами. Отсутствие такого описания может привести к ошибкам при компиляции, компоновке или выполнении программы. При описании внешнего объекта используйте ключевое слово С...
 

作为测试的一个变体--你也可以在每个测试中只插入不同的数组--在我的例子中,arr1,arr2...

即tst1_arr1[],tst1_arr2[] ....和tst2_arr1[],tst2_arr2[]


这将是一个更公平的测试。

 
Igor Makanu:

我不知道在没有调试器的情况下如何测试--至少你可以看到指令在时钟周期内的执行时间。

嗯,是的--你不能没有调试器。而在时钟时间里,有...

 
Roman:

这很奇怪。
在循环条件中使用ArraySize(arr)显示的时间比使用cnt变量少。
以前是反之亦然。也许这是一个错误?它不应该是这样的。

那里有一个随机的结果。在编译时,对具有数组大小 值的存储单元的访问是展开的,而数组大小将被提前接收并放入存储单元,当数组形成时,即使数组是动态的,具有数组大小的单元和一个变量的值将有相同的访问时间。

而从编译器在3-4年的计算机科学课程中所做的这句话来看......一般来说,我希望足够必要的框架水平不会使我在MCL环境中非常紧张)