错误、漏洞、问题 - 页 2161

 
Renat Fatkhullin:


让我们仔细检查一下整个代码。有趣的是,要找到真正的原因是什么。

酷!谢谢你!我也很感兴趣。

而sqrt确实非常快。不到一纳秒:))。太棒了!

 
Nikolai Semko:

试过静态数组--同样的事情。

就像sqrt那样快,我很难相信这个函数能比仅仅读取一个数组元素 快10倍。

在这一点上,很多旧的优化技术已不再起作用。


此外,如果在我的例子中要减少画布的尺寸,比如50x50(为此有一个输入参数Size,你需要设置50而不是0)。

而且阵列会小得多(5000个元素),速度图片看起来会有很大不同。现在已经没有这么强烈的对比了。

但我不明白的是,数组的大小 是否影响访问其项目的速度

你的计算没有干净的证明,你是根据非常垃圾的代码来做假设的。

你忽略了大量的辅助计算,这些计算在你的代码中,对结果有很大影响。

 
Renat Fatkhullin:


你的计算没有干净的证明,你是在非常混乱的代码基础上做的假设。

你忽略了大量的辅助计算,这些计算在你的代码中,对结果有很大影响。

我所看到的是,仅仅通过将sqrt改为从数组中简单读取,整个计算速度就下降了4倍。而在这个相当大的每个像素的计算中,sqrt的总体比例几乎不超过10%,甚至是百分之几。

一个明显的反常现象!

我甚至犯了一个错误,说对一个数组元素 的访问时间是平方时间的10倍。鉴于sqrt的速度如此之快,而整体的速度又如此之慢,就更多了。

 
Nikolai Semko:

我只能看到,通过简单地将sqrt改为从数组中简单读取,整个计算速度下降了4倍。而在这个相当大的每个像素的计算中,sqrt的总体比例几乎不超过10%,甚至是百分之几。

一个明显的反常现象!

我已经解释了原因。九十年代数学的优化不再起作用了。

但你一直根据现实生活中的垃圾代码做出以下断言。在植物方面,他们是错误的。

在这种技术[不]纯洁的水平上,我不会讨论这些问题。

 
Renat Fatkhullin:

我已经解释了原因。九十年代数学的优化不再起作用了。

但你一直根据真正的垃圾代码做出以下论断。似是而非的缺陷。

在这种技术[不]纯洁的水平上,我不会讨论这些问题。

我不明白你在说什么数学优化。而且我并没有做任何断言,只是想知道刹车的来源是什么。

这个原始代码中的杂乱和优化在哪里?

#include <Canvas\Canvas.mqh>

void OnStart()
  {
   ChartSetInteger(0,CHART_FOREGROUND,true);
   CCanvas C;
   int Width=(ushort)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS);                               // получаем Ширину окна
   int Height=(ushort)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS);                             // получаем Высоту окна
   if(!C.CreateBitmapLabel(0,0,"CanvasExamlple",0,0,Width,Height,COLOR_FORMAT_XRGB_NOALPHA)) // создаем канвас размером текущего окна
   Print("Error creating canvas: ",GetLastError()); 
   uint i=0,j=100000;
   int size=Width*Height;
   uchar h[25600];
   for (int w=0;w<25600;w++) 
   h[w]= uchar(128+128*sin(double(w)/256));//создаем массив для ускорения работы
   double X1=0,Y1=0,X2=0,Y2=0,X3=0,Y3=0,X4=0,Y4=0;
   while(!IsStopped())
     {
      int pos=int(i%size);
      if(pos==0)
        {
         C.Update();
         //Sleep(30);
         X1= Width/2-(sin((double)j/100)*(double)Width/2);
         Y1= Height/2-(cos((double)j/140)*(double)Height/2);
         X2= Width/2+(cos((double)j/80)*(double)Width/2);
         Y2= Height/2+(sin((double)j/20)*(double)Height/2);
         X3= Width/2+(cos((double)j/85)*(double)Width/2);
         Y3= Height/2+(sin((double)j/65)*(double)Height/2);
         X4= Width/2+(cos((double)j/152)*(double)Width/2);
         Y4= Height/2+(sin((double)j/42)*(double)Height/2);
         j++;
        }
      int X=pos%Width;
      int Y=int(pos/Width);
      double D1=sqrt((X1-X)*(X1-X)+(Y1-Y)*(Y1-Y));
      double D2=sqrt((X2-X)*(X2-X)+(Y2-Y)*(Y2-Y));
      double D3=sqrt((X3-X)*(X3-X)+(Y3-Y)*(Y3-Y));
      double D4=sqrt((X4-X)*(X4-X)+(Y4-Y)*(Y4-Y));
      double d= (D1+D2)/(D1+D2+D3+D4);
      C.PixelSet(X,Y,XRGB(h[int(d*11520)],h[int(d*17920)],h[int(d*6400)]));
      i++;
     }
   C.Destroy();
  }

你可以使用这种更通用的代码,但由于使用了循环和数组,图像取景的速度几乎减半。

#include <Canvas\Canvas.mqh>
#property script_show_inputs 
input int N=8; // количество центов гравитации

void OnStart()
  {
   ChartSetInteger(0,CHART_FOREGROUND,true);
   CCanvas C;
   int Width=(ushort)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS);                               // get Window width
   int Height=(ushort)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS);                             // get Window height 
   if(!C.CreateBitmapLabel(0,0,"CanvasExamlple",0,0,Width,Height,COLOR_FORMAT_XRGB_NOALPHA)) // create canvas with the size of the current window
      Print("Error creating canvas: ",GetLastError());
   uint i=0,j=100000;
   int size=Width*Height;
   uchar h[];
   ArrayResize(h,25600);
   for(int w=0;w<25600;w++) h[w]=uchar(128+128*sin(double(w)/256)); //create an array to speed up the work
                                                                  
   int k[]; ArrayResize(k,N*2);
   for(int w=0;w<N*2;w++) k[w]=20+rand()%200;
   double XP[],YP[],D[],D1[];
   ArrayResize(XP,N);
   ArrayResize(YP,N);
   ArrayResize(D,N);
   ArrayInitialize(XP,0);
   ArrayInitialize(YP,0);
  
   while(!IsStopped())
     {
      int pos=int(i%size);
      if(pos==0)
        {
         C.Update();
         for(int w=0;w<N;w++)
           {
            XP[w]= Width/2-(sin((double)j/k[2*w])*(double)Width/2);
            YP[w]= Height/2-(cos((double)j/k[2*w+1])*(double)Height/2);
           }
         j++;
        }
      int X=pos%Width;
      int Y=int(pos/Width);

      for(int w=0;w<N;w++) D[w]= sqrt((XP[w]-X)*(XP[w]-X)+(YP[w]-Y)*(YP[w]-Y));
      double S1=0,S2=0;
      for(int w=0;w<N/2;w++) S1+=D[w];
      for(int w=0;w<N;w++) S2+=D[w];
      double d=S1/S2;
      
      C.PixelSet(X,Y,XRGB(h[int(d*11520)],h[int(d*17920)],h[int(d*6400)]));
      i++;
     }
   C.Destroy();
  }
//+------------------------------------------------------------------+
 

优化数学:尝试使用数组而不是sqrt。

你没有看到杂乱无章的东西,这是你对性能测试规则误解的根源。如果你测试预先计算的数组与计算,你需要删除一切多余的东西。绝对是一切不必要的。

你做了很多断言。你需要能够从接受者的角度来阅读文本,并清洗掉作者的非工作防御。

 
Renat Fatkhullin:

优化数学:尝试使用数组而不是sqrt。

哦,让sqrt见鬼去吧。我已经意识到,就这个特定的功能而言,它是没有意义的。尝试有什么错呢?但现在我知道了。

顺便说一下,在这个例子中,使用h[]数组也比使用sin()获得了相当大的速度。

这个问题是关于其他方面的。

为什么使用对大数组单元的访问会使计算时间增加数倍,而预期只增加百分之几?

你没有看到垃圾,这是你对性能测试规则误解的根源。如果你要测试预先计算的数组与计算,你需要删除一切多余的东西绝对是一切不必要的。

你知道,雷纳特,被你打一巴掌并不丢人,甚至是一种荣誉。

根据我的理解,垃圾是不必要的东西,可以而且应该被清除。但在这种情况下,没有什么可清理的,否则代码将停止工作。

我不是在测试"预先计算的阵列与计算",而是在分析帧的形成速度

在我的情况下,我不需要任何测试,因为我有一台弱小的笔记本电脑,不需要任何测试就可以看到25帧和6帧之间的区别。

你所做的断言是巨大的。你需要能够从接受者的角度来阅读文本,并为他们清除作者的非工作防线。

我只做了几个假设,而不是断言。

- "合乎逻辑的是,从数组SQRT[x]中读取的速度要比sqrt(x)函数快。"

-"人们可能会认为,编译器正在以某种奇怪的方式访问一个大的数组,在每个循环转折处,它似乎 "忘记 "了数组,每次都做某种服务索引。"

但我还是要大胆地说出这句话,因为虽然我是一个自学成才的程序员,但自学成才的经验很丰富,对处理器内部的流程也有所了解,因为有一段时间我最喜欢的程序是Numega SoftIce,通过它我在汇编水平上挖出了大量的外来代码。

- 我向你保证,在你的编译器中存在一个关于访问数组的算法错误,(也许它只出现在足够大的数组中),如果你在这个方向上付出努力,你的团队会很容易发现这个问题。而 我的例子 将帮助你。

我甚至可以争辩说。))

 

当你循环浏览一个表时,每次下一次访问它时,它都有可能在处理器的缓存中。这就是为什么它运行得更快。

如果访问之间有任何代码,就有可能出现缓存缺失。这也解释了处理大表和小表的区别。

此外,还有其他非显而易见的情况。因此,有必要对最终的非简化版本的代码进行测试。

 
伙计们,你们如何在函数模板中判断一个 具有枚举类型的函数被调用了
 
Vladimir Pastushak:
伙计们告诉我,在函数模板中如何确定带有枚举类型的函数被调用
enum是一个整数的枚举。
0,1,2,3 ......,等等。
原因: