向#define专家提问 - 页 7

 
Alexandr Andreev:

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

正如它在第一个版本中所做的那样。

是的,错过了这一点。纠正了我的帖子。

 
Valeriy Yastremskiy:

那里有一个随机的结果。编译展开了对具有数组大小值的存储单元的访问,当数组形成时,数组大小将被提前获得并置于存储单元中,即使数组是动态的,具有数组大小和具有可变值的单元将具有相同的访问时间。

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

相信我,一般的学生通常FIVT只是零与加),因为没有经验,而没有经验的知识很快就无处可去(被遗忘),他们的例子非常奇怪,要花几年时间才能让学生明白在哪里和如何使用它们。这是指如果你与有经验的程序员相比。

 
Alexandr Andreev:

相信我,一般的FIVT学生通常是零分加分),因为经验为零,没有经验的知识很快就会无影无踪(被遗忘),而且他们的例子非常奇怪,学生要过几年才会明白它们可以用在哪里以及如何使用。这是指如果你与有经验的程序员相比。

这是可以理解的。我不明白为什么你要教如何制作一个编译器。这就像教人如何创造自己的语言一样。 很明显,语言是一个类别,但不是每只鸟都能先验地飞行。好吧,正如我在上面已经提到的,"错误"、"缺陷"、"问题 "也与飞行中优化编译的问题有关。

 

这个话题是关于定义的,不是关于循环的 ))

但我还是不明白,定义代码有意义吗,比如说,用户定义的函数。
希望失效的代码能在可执行文件中更快地执行。
还是说这是一个误解?因为替换只是一个预编译动作,它只对加速构建有意义。

 
Roman:

这个话题是关于定义的,不是关于循环的 ))

但我还是不明白,定义代码有意义吗,比如说,用户定义的函数。
希望失效的代码能在可执行文件中更快地执行。
还是说这是一个误解?因为替换只是一个预编译的动作,而加快构建的速度也是合乎逻辑的。

我刚刚给你看了一个例子,其中使用了3个外部函数...对照其展开的形式。所以不会有加速的现象。

关于交易、自动交易系统和策略测试的论坛

向#define专家提问

Alexandr Andreev, 2020.11.02 19:49

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
Внешние функции, определенные в другом модуле, должны быть явно описаны. Описание включает в себя тип возвращаемого значения, имя функции и набор входных параметров с их типами. Отсутствие такого описания может привести к ошибкам при компиляции, компоновке или выполнении программы. При описании внешнего объекта используйте ключевое слово С...
 
Alexandr Andreev:

我刚刚给你看了一个例子,其中使用了3个外部函数...对照其展开的形式。所以不会有加速的现象。


我明白了。然后向fxsaber问好。对所有的东西都不支持的粉丝。


Alexandr Andreev:

证明我错了)

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

至于ArraySize()和变量。我还是要回到这个问题上。
以下是我在测试中所改变的内容。循环计算PI的数量。
在第一个例子中,循环的条件使用ArraySize()。
在第二个例子中,使用了num_steps这个变量。
这是有区别的。

ArraySize()函数

void OnStart()
{
    int arr[];
    int num_steps = ArrayResize(arr, 1000000000);

    double x, pi, sum=0.0;
    double step = 1.0/(double)num_steps;
    
    ulong t = GetMicrosecondCount();
    
    for (int i = 0; i<ArraySize(arr); i++)
    {
       x = (i + .5) * step;
       sum = sum + 4.0 / (1.0 + x * x);
    }
    
    pi = sum*step;
        
    t = GetMicrosecondCount() - t;
   
   printf("The value of PI is %1.12f ", pi);
   PrintFormat("Total time to calculate PI was %5.3f ms\n", t / 1000.0);
}

三次运行的脚本。

2020.11.02 23:56:51.556 TestScript (USDJPY,M1)  The value of PI is 3.141592653590 
2020.11.02 23:56:51.556 TestScript (USDJPY,M1)  Total time to calculate PI was 4049.179 ms
2020.11.02 23:56:51.556 TestScript (USDJPY,M1)  
2020.11.02 23:56:57.928 TestScript (USDJPY,M1)  The value of PI is 3.141592653590 
2020.11.02 23:56:57.928 TestScript (USDJPY,M1)  Total time to calculate PI was 4183.364 ms
2020.11.02 23:56:57.928 TestScript (USDJPY,M1)  
2020.11.02 23:57:03.884 TestScript (USDJPY,M1)  The value of PI is 3.141592653590 
2020.11.02 23:57:03.884 TestScript (USDJPY,M1)  Total time to calculate PI was 4034.098 ms
        


变量num_steps。

void OnStart()
{
    int arr[];
    int num_steps = ArrayResize(arr, 1000000000);

    double x, pi, sum=0.0;
    double step = 1.0/(double)num_steps;
    
    ulong t = GetMicrosecondCount();
    
    for (int i = 0; i<num_steps; i++)
    {
        x = (i + .5) * step;
        sum = sum + 4.0 / (1.0 + x * x);
    }
    
    pi = sum*step;
        
    t = GetMicrosecondCount() - t;
   
   printf("The value of PI is %1.12f ", pi);
   PrintFormat("Total time to calculate PI was %5.3f ms\n", t / 1000.0);
}

三次运行的脚本。

2020.11.03 00:08:09.269 TestScript (USDJPY,M1)  The value of PI is 3.141592653590 
2020.11.03 00:08:09.271 TestScript (USDJPY,M1)  Total time to calculate PI was 3955.325 ms
2020.11.03 00:08:09.271 TestScript (USDJPY,M1)  
2020.11.03 00:08:15.578 TestScript (USDJPY,M1)  The value of PI is 3.141592653590 
2020.11.03 00:08:15.578 TestScript (USDJPY,M1)  Total time to calculate PI was 3950.568 ms
2020.11.03 00:08:15.578 TestScript (USDJPY,M1)  
2020.11.03 00:08:22.469 TestScript (USDJPY,M1)  The value of PI is 3.141592653590 
2020.11.03 00:08:22.469 TestScript (USDJPY,M1)  Total time to calculate PI was 3927.110 ms
        
 
Roman:

我明白了。然后向fxsaber问好。一个喜欢把所有东西都定义成一排的人。

至于ArraySize()和变量。我还是会回到这个问题上。
这是我修改的测试。循环计算PI的数量。
在第一个例子中,循环的条件使用ArraySize()
在第二个例子中,
使用了num_steps这个变量
这是有区别的。

ArraySize()函数

三次运行的脚本。


变量num_steps。

三次运行的脚本。

在这些计算中没有明显的区别。我把所有这些放在一个代码中,结果是不同的,有一个是第一种变体获胜的情况

))中的任何数组都有一个变量,负责数组的当前大小,所以在大多数语言中。

ArraySize函数 告诉编译器返回这个变量的值,也就是说,它用这个变量代替这个函数。 由于μl数组不能被引用,指针明确地指向这个变量,正好是内存中的rocette地址。从技术上讲,所有这些测试都是在尝试比较两个常规变量。这是展开函数的属性,在我的例子中,4个函数原谅0个函数,其中3个就在循环体中,也就是说,有40000000000个函数调用与没有函数调用的比较。而我们看到了一个隐含的差异,这个差异太小了,无法注意到--因为它把代码放在可执行文件中....。我们比较的是同一件事。

而所有这些计算--它们越是复杂,就越是没有意义。

举个例子更容易,在一种情况下,我们调用一百个函数,函数中的函数......而在另一种情况下,所有这些都以扩大的形式出现--而且不会有任何区别。因为ArraySize(mas)==mas[]。尺寸

Документация по MQL5: Операции с массивами / ArraySize
Документация по MQL5: Операции с массивами / ArraySize
  • www.mql5.com
"Нулевое измерение = Размер массива / (Первое измерение * Второе измерение * Третье измерение)"
 

虽然由于某些原因,π的例子确实有一个差异.....,通过过冲频率,(节录)虽然这纯粹是随机过冲

而它相当于每10亿个输出的1ms,尽管这没有明确地尝试将变量与变量进行比较,而且散点变得更大))


 
Alexandr Andreev:

与这些计算结果没有明显区别。把它全部放在一个代码中,结果是不同的,有一些是第一个选项获胜的地方

)) µl中的每个数组都有一个负责当前数组大小的变量,所以在大多数语言中。

ArraySize函数 告诉编译器返回这个变量的值,也就是说,它用这个变量代替这个函数。 由于μl数组不能被引用,指针明确地指向这个变量,正好是内存中的rocette地址。从技术上讲,所有这些测试都是在尝试比较两个常规变量。这 是展开函数的属性,在我的例子中,4个函数原谅0个函数,其中3个就在循环体中,也就是说,有40000000000个函数调用与没有函数调用的比较。而我们看到了一个隐含的差异,这个差异太小了,无法注意到--因为它把代码放在可执行文件中....。我们比较的 是同一件事。

而所有这些计算--它们越是复杂,就越是没有意义。

举个例子更容易,在一种情况下,我们调用一百个函数,函数中的函数......而在另一种情况下,所有这些都以扩大的形式出现--而且不会有任何区别。因为ArraySize(mas)==mas[]。尺寸

在循环体中执行什么并不重要。这只是一个测试用的负载。
例子中比较了对循环条件中的函数或变量的引用。

我不是一个汇编员,但我认为从汇编员指令的角度来看,这不是一回事。
而如果它也被包裹在一个类中,那就肯定不是一回事了。

一个函数有一条额外的指令来从存储单元中获取一个值,即函数调用存储单元获取一个值,然后才返回结果。
一个变量已经有了这个值,这个变量并没有引用任何地方,它立即返回结果。

 
Roman:

在循环的主体中进行什么并不重要。这只是一个测试用的负载。
这些例子比较了循环条件中对函数或变量的引用。

我不是汇编专家,但我认为从汇编指令的角度来看,这不是一回事。
而如果它也被包裹在一个类中,那就肯定不是一回事了。

一个函数有一条额外的指令来从存储单元中获取一个值,即函数调用存储单元获取一个值,然后才返回结果。
一个变量已经有了这个值,这个变量并没有引用任何地方,它立即返回结果。

) 好吧,这不是它的工作方式)

 
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
  {
   int mas[];
   int mas1[300];
   int mas2[300];
   int mas3[300];
   int mas4[300];
   int mas5[300];
   int mas6[300];
   int z=300;
   int size=100000000;
   ArrayResize(mas,size);
   ulong r=0;
   ulong r1=0;
   ulong r2=0;
   int random;
   ulong max=100; 
   int t=0;
   int tr=0; 
   MathSrand(10);
    int num_steps=ArraySize(mas);
    double x, pi, sum=0.0;
    double step = 1.0/(double)num_steps;
    
     int v=size;
    ulong t1 = GetMicrosecondCount();
     
    
  // for(ulong z=0; z<max; z++)
     {
      for(ulong i=0; i<ArraySize(mas); i++)
        { 
        r2+=ArraySize(mas);
        r2+=ArraySize(mas1);
        r2+=ArraySize(mas2);
        r2+=ArraySize(mas3);
        r2+=ArraySize(mas4);
        r2+=ArraySize(mas5);
        r2+=ArraySize(mas6);
        r2+=ArraySize(mas1);
        r2+=ArraySize(mas2);
        r2+=ArraySize(mas3);
        r2+=ArraySize(mas4);
        r2+=ArraySize(mas5);
        r2+=ArraySize(mas6);
        r2+=ArraySize(mas1);
        r2=r2/10;
        }

     }  
   ulong t2=GetMicrosecondCount();
   //for(ulong z=0; z<max; z++)
     {
      for(ulong i=0; i<v; i++)
        { 
        r1+=z;
        r1+=z;
        r1+=z;
        r1+=z;
        r1+=z;
        r1+=z;
        r1+=z;
        r1+=z;
        r1+=z;
        r1+=z;
        r1+=z;
        r1+=z;
        r1+=z;
        r1+=z;
        r1+=z;
        r1=r1/10;
        }
     }
   
   int pi2 = sum*step;
   ulong t3=GetMicrosecondCount();
   Print(t2-t1,"  ",t3-t2," ",r," ",r1," ",r2," ",pi," ",pi2);
// Templ();
  }

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

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

几乎每一次运行,领导者都会改变

最长的一个是除法))))