错误、漏洞、问题 - 页 2165 1...215821592160216121622163216421652166216721682169217021712172...3184 新评论 Roffild 2018.03.13 23:02 #21641 我没有得到负值的优化图。 这些数据可以在优化结果中找到。 尝试在你的EA中设置负值。值可以是*-1来检查。 Nikolai Semko 2018.03.13 23:30 #21642 Renat Fatkhullin:经检查发现。 SQRT被直接映射到CPU指令中SQRT+数学计算 是在没有分支的情况下进行的,对于一条指令(128位数据),可以一次计算两个根 这段代码变成了以下汇编的SSE代码。 这实际上是一件艺术作品。一个汇编指令的4次调用就能计算出8个根。两个双数在一次调用中被评估。当通过一个数组进行操作时,一切都像往常一样,检查、分支和转换双数->整数索引的损失。在这个例子中处理数组时,不断有FPU/ALU混合,这对生产力非常不利。对动态数组访问的优化非常好--无可非议。但混合FPU/ALU操作+双数->整数+分支的方式会浪费时间总的结论是:由于完美的优化,数学在MQL5中获胜。这里输的不是数组,而是数学赢了。非常感谢您提供的宝贵信息。 当然,这个消息更令人高兴。这真的很酷! 我总是说,MQs是一种美。 但我也意识到,对于数据类型的混合,人们必须非常小心。但是,未雨绸缪就是先入为主。 如果能从开发商那里得到一些这方面的建议,那就太好了。 现在我将对普通变量和数组的类型进行实验。我想知道会有什么结果。 Nikolai Semko 2018.03.14 00:44 #21643 Renat Fatkhullin:我一直在做实验。 我似乎仍然无法把拼图拼起来。 我已经做了两个变体。第一种--把所有东西都转换为int类型。第二条--要翻倍。 是的,它变得有点快。但主要的缺点仍然存在。 这里是带有int变体的主制动块。 if(arr) { // расчет квадратных корней через массив значений SQRT[] D1=SQRT[((X1-X)*(X1-X)+(Y1-Y)*(Y1-Y))]; D2=SQRT[((X2-X)*(X2-X)+(Y2-Y)*(Y2-Y))]; D3=SQRT[((X3-X)*(X3-X)+(Y3-Y)*(Y3-Y))]; D4=SQRT[((X4-X)*(X4-X)+(Y4-Y)*(Y4-Y))]; D5=SQRT[((X5-X)*(X5-X)+(Y5-Y)*(Y5-Y))]; D6=SQRT[((X6-X)*(X6-X)+(Y6-Y)*(Y6-Y))]; D7=SQRT[((X7-X)*(X7-X)+(Y7-Y)*(Y7-Y))]; D8=SQRT[((X8-X)*(X8-X)+(Y8-Y)*(Y8-Y))]; } 它只有int类型,没有类型混合。SQRT数组本身已经变成了int。 它的工作速度只有10%。 双重变体的情况也类似。 嗯,一切都相同--只是在第一种情况下,计算的是sqrt()函数,并且有类型混合。 而第二种情况指的是一个int数组,没有类型混合,理论上应该只使用ALU。 但第二种方式要慢3倍。好吧,不管是什么原因,这就是阵列。 还有一件重要的事。 在int的例子中,如果画布的尺寸是100x100,即有以下参数 我们在访问数组时获得了速度优势。 例如,当使用大小为20 000的SQRT数组时,我们获得15-20%的收益,而当使用大小为3 000 000的数组时,我们损失200%,尽管数学上绝对相同。 所以阵列的大小是导致刹车的原因? 附加的文件: LSD_double.mq5 10 kb LSD_int.mq5 10 kb Renat Fatkhullin 2018.03.14 00:54 #21644 人们早就失去了理解现代C++编译器结果的能力。 此外,你有一堆乱七八糟的代码,这意味着建立天真的公理 "如果这些条件,那么结果将是这样 "的可能性几乎为零。也就是说,最终的优化将重新安排一切,以至于你的假设将产生百分之几十的不同结果,即使代码中的微小变化。 再看看把8个根塞进4个汇编命令,就会发现你没有机会断言、要求或呼吁你的逻辑。长期以来,优化器在程序员无法企及的水平上运行。 编译器分解根的方式是一种艺术。而你试图用数组来打败它,甚至没有理解最简单的约束--从数组中读取已经是一种失败。完美的寄存器工作和批量计算的根与分支(惩罚)和爬到内存的频繁缓存错过。 你问 "为什么它在小缓冲区上更快,而在大缓冲区上却惨遭失败",因为你对处理器的L1/L2/L3缓存一无所知。如果你进入了缓存,很快就会被计算在内。没有抓到--等待几十个周期从上层缓存或内存中读取数据。 Nikolai Semko 2018.03.14 01:05 #21645 Renat Fatkhullin:人们早就失去了理解现代C++编译器结果的能力。 此外,你有一堆乱七八糟的代码,这意味着建立天真的公理 "如果这些条件,那么结果将是这样 "的可能性几乎为零。也就是说,最终的优化将重新安排一切,以至于你的假设将产生百分之几十的不同结果,即使代码中的微小变化。 再看看把8个根塞进4个汇编命令,就会发现你没有机会断言、要求或呼吁你的逻辑。长期以来,优化器在程序员无法企及的水平上运行。我完全可以看到你与VS相比的结果,我对此感到很高兴。 但问题仍然存在。 我对混乱的工作代码表示歉意,但我们只是在讨论这一段代码,并比较两种执行方案。 if(arr) { // расчет квадратных корней через массив значений SQRT[] D1=SQRT[((X1-X)*(X1-X)+(Y1-Y)*(Y1-Y))]; D2=SQRT[((X2-X)*(X2-X)+(Y2-Y)*(Y2-Y))]; D3=SQRT[((X3-X)*(X3-X)+(Y3-Y)*(Y3-Y))]; D4=SQRT[((X4-X)*(X4-X)+(Y4-Y)*(Y4-Y))]; D5=SQRT[((X5-X)*(X5-X)+(Y5-Y)*(Y5-Y))]; D6=SQRT[((X6-X)*(X6-X)+(Y6-Y)*(Y6-Y))]; D7=SQRT[((X7-X)*(X7-X)+(Y7-Y)*(Y7-Y))]; D8=SQRT[((X8-X)*(X8-X)+(Y8-Y)*(Y8-Y))]; } else // расчет квадратных корней через функцию кв. корня sqrt() { D1=(int)sqrt((X1-X)*(X1-X)+(Y1-Y)*(Y1-Y)); D2=(int)sqrt((X2-X)*(X2-X)+(Y2-Y)*(Y2-Y)); D3=(int)sqrt((X3-X)*(X3-X)+(Y3-Y)*(Y3-Y)); D4=(int)sqrt((X4-X)*(X4-X)+(Y4-Y)*(Y4-Y)); D5=(int)sqrt((X5-X)*(X5-X)+(Y5-Y)*(Y5-Y)); D6=(int)sqrt((X6-X)*(X6-X)+(Y6-Y)*(Y6-Y)); D7=(int)sqrt((X7-X)*(X7-X)+(Y7-Y)*(Y7-Y)); D8=(int)sqrt((X8-X)*(X8-X)+(Y8-Y)*(Y8-Y)); } 这里没有垃圾。 你说" 对 动态数组 访问的优化非常好,无可挑剔"。 但是...见我之前的留言。 你如何解释我的最后一个实验? "也就是说,当我们使用一个大小为20,000的SQRT数组时,我们的收益为15-20%,而当我们使用一个大小为3,000,000的数组时,在完全相同的数学运算下,我们会损失200%。所以,阵列的大小是刹车的原因?" Renat Fatkhullin 2018.03.14 01:14 #21646 仔细阅读我之前的回复--它是完整的,有一个确切的答案。 我将简单地解释你的问题:从性能和影响因素的角度,深思熟虑地阅读五篇关于处理器设计的技术文章。没有这些你就无法进行讨论,因为你需要解释基础知识。 Nikolai Semko 2018.03.14 02:32 #21647 Renat Fatkhullin:编译器对根的分解方式是一种艺术。而你想用数组来打败它,却连最简单的约束都不明白--从数组中读取已经是一种失败。完美的寄存器工作和批量计算的根与分支(惩罚)和爬到内存的频繁缓存错过。 你问的是 "为什么在小的缓冲区上速度更快,而在大的缓冲区上却振聋发聩",因为你根本不了解处理器的L1/L2/L3缓冲区的情况。如果你进入了缓存,很快就会被计算在内。如果你没有得到它,你将不得不等待几十个周期,从上层缓存或内存中读取数据。雷纳特-法特库林。仔细阅读我之前的回复--它已经完成了一个确切的答案。让我简单解释一下你的问题:在性能和影响因素方面,深思熟虑地阅读五篇关于处理器设计的技术文章。没有这些,你就无法进行讨论,因为你需要解释基本的东西。耶!!!。 终于来了! 你,雷纳特,应该为所有的事情被掐死。 对我来说,现在的情况更清楚了。 我在责备你的编译器时是错的。我很抱歉,我错了。我可能已经猜到,原因在于处理器的有限缓存。我在现代处理器方面真的很差,我真的需要读一读。 不过,我写下这段代码--小白鼠--并掀起这股浪潮,也不是没有原因的。 因此,对于那些正在阅读这个主题的程序员,我将总结一下我个人在这一波中所发现的问题。 sqrt()函数和最有可能的许多其他基本函数都非常快,而且不是在编译器层面执行,而是在CPU层面执行。MQL5编译器在优化数学逻辑方面非常强大,可以轻松地击败现代VS C++编译器。这是非常鼓舞人心的。在资源密集型的任务中,尽量不要混合类型是合理的。混合类型会导致计算速度降低。尺寸的重要性!( 我指的是阵列的大小:))因为处理器的多级缓存 工作的特殊性和它的有限大小。而程序员最好注意数组的总大小,了解使用大数组可能会大大影响计算的速度。据我所知,重点是关于总大小不超过512kB的数组的相对舒适的工作,它是~65000个双倍类型的元素或~130000个int类型的元素。 我根据这些信息去修改我的代码。我经常滥用数组的大小。 谢谢大家! Alexandr Bryzgalov 2018.03.14 06:55 #21648 我怎么知道十字准星按钮是被按下还是被释放了? 你可以在按下鼠标滚轮时抓取,但如果鼠标不在使用中,你怎么能做到这一点? Alexey Viktorov 2018.03.14 07:18 #21649 Alexandr Bryzgalov:我怎么知道十字准星按钮是被按下还是被释放了? 你可以抓住鼠标滚轮的点击,但如果鼠标不在使用中,那怎么办?在需要的时候强迫它或把它推回去如何? 图表_十字绣_工具通过按下鼠标中键启用/禁用访问 "十字准线 "工具bool (默认值为true) Alexandr Bryzgalov 2018.03.14 07:22 #21650 Alexey Viktorov:如果有必要,是否可以强制或推倒重来? 图表_十字绣_工具通过按下鼠标中键来启用/禁用 "十字准线 "工具bool (默认为真)据我所知,它只能访问工具,但不能关闭它。 1...215821592160216121622163216421652166216721682169217021712172...3184 新评论 您错过了交易机会: 免费交易应用程序 8,000+信号可供复制 探索金融市场的经济新闻 注册 登录 拉丁字符(不带空格) 密码将被发送至该邮箱 发生错误 使用 Google 登录 您同意网站政策和使用条款 如果您没有帐号,请注册 可以使用cookies登录MQL5.com网站。 请在您的浏览器中启用必要的设置,否则您将无法登录。 忘记您的登录名/密码? 使用 Google 登录
我没有得到负值的优化图。
这些数据可以在优化结果中找到。
尝试在你的EA中设置负值。值可以是*-1来检查。
经检查发现。
这段代码变成了以下汇编的SSE代码。
这实际上是一件艺术作品。一个汇编指令的4次调用就能计算出8个根。两个双数在一次调用中被评估。
总的结论是:由于完美的优化,数学在MQL5中获胜。这里输的不是数组,而是数学赢了。
非常感谢您提供的宝贵信息。
当然,这个消息更令人高兴。这真的很酷!
我总是说,MQs是一种美。
但我也意识到,对于数据类型的混合,人们必须非常小心。但是,未雨绸缪就是先入为主。
如果能从开发商那里得到一些这方面的建议,那就太好了。
现在我将对普通变量和数组的类型进行实验。我想知道会有什么结果。
我一直在做实验。
我似乎仍然无法把拼图拼起来。
我已经做了两个变体。第一种--把所有东西都转换为int类型。第二条--要翻倍。
是的,它变得有点快。但主要的缺点仍然存在。
这里是带有int变体的主制动块。
它只有int类型,没有类型混合。SQRT数组本身已经变成了int。
它的工作速度只有10%。
双重变体的情况也类似。
嗯,一切都相同--只是在第一种情况下,计算的是sqrt()函数,并且有类型混合。
而第二种情况指的是一个int数组,没有类型混合,理论上应该只使用ALU。
但第二种方式要慢3倍。好吧,不管是什么原因,这就是阵列。
还有一件重要的事。
在int的例子中,如果画布的尺寸是100x100,即有以下参数
我们在访问数组时获得了速度优势。
例如,当使用大小为20 000的SQRT数组时,我们获得15-20%的收益,而当使用大小为3 000 000的数组时,我们损失200%,尽管数学上绝对相同。
所以阵列的大小是导致刹车的原因?
人们早就失去了理解现代C++编译器结果的能力。
此外,你有一堆乱七八糟的代码,这意味着建立天真的公理 "如果这些条件,那么结果将是这样 "的可能性几乎为零。也就是说,最终的优化将重新安排一切,以至于你的假设将产生百分之几十的不同结果,即使代码中的微小变化。
再看看把8个根塞进4个汇编命令,就会发现你没有机会断言、要求或呼吁你的逻辑。长期以来,优化器在程序员无法企及的水平上运行。
编译器分解根的方式是一种艺术。而你试图用数组来打败它,甚至没有理解最简单的约束--从数组中读取已经是一种失败。完美的寄存器工作和批量计算的根与分支(惩罚)和爬到内存的频繁缓存错过。
你问 "为什么它在小缓冲区上更快,而在大缓冲区上却惨遭失败",因为你对处理器的L1/L2/L3缓存一无所知。如果你进入了缓存,很快就会被计算在内。没有抓到--等待几十个周期从上层缓存或内存中读取数据。人们早就失去了理解现代C++编译器结果的能力。
此外,你有一堆乱七八糟的代码,这意味着建立天真的公理 "如果这些条件,那么结果将是这样 "的可能性几乎为零。也就是说,最终的优化将重新安排一切,以至于你的假设将产生百分之几十的不同结果,即使代码中的微小变化。
再看看把8个根塞进4个汇编命令,就会发现你没有机会断言、要求或呼吁你的逻辑。长期以来,优化器在程序员无法企及的水平上运行。
我完全可以看到你与VS相比的结果,我对此感到很高兴。
但问题仍然存在。
我对混乱的工作代码表示歉意,但我们只是在讨论这一段代码,并比较两种执行方案。
这里没有垃圾。
你说" 对 动态数组 访问的优化非常好,无可挑剔"。
但是...见我之前的留言。
你如何解释我的最后一个实验?
"也就是说,当我们使用一个大小为20,000的SQRT数组时,我们的收益为15-20%,而当我们使用一个大小为3,000,000的数组时,在完全相同的数学运算下,我们会损失200%。
所以,阵列的大小是刹车的原因?"
仔细阅读我之前的回复--它是完整的,有一个确切的答案。
我将简单地解释你的问题:从性能和影响因素的角度,深思熟虑地阅读五篇关于处理器设计的技术文章。没有这些你就无法进行讨论,因为你需要解释基础知识。
编译器对根的分解方式是一种艺术。而你想用数组来打败它,却连最简单的约束都不明白--从数组中读取已经是一种失败。完美的寄存器工作和批量计算的根与分支(惩罚)和爬到内存的频繁缓存错过。
你问的是 "为什么在小的缓冲区上速度更快,而在大的缓冲区上却振聋发聩",因为你根本不了解处理器的L1/L2/L3缓冲区的情况。如果你进入了缓存,很快就会被计算在内。如果你没有得到它,你将不得不等待几十个周期,从上层缓存或内存中读取数据。仔细阅读我之前的回复--它已经完成了一个确切的答案。
让我简单解释一下你的问题:在性能和影响因素方面,深思熟虑地阅读五篇关于处理器设计的技术文章。没有这些,你就无法进行讨论,因为你需要解释基本的东西。
耶!!!。
终于来了!
你,雷纳特,应该为所有的事情被掐死。
对我来说,现在的情况更清楚了。
我在责备你的编译器时是错的。我很抱歉,我错了。我可能已经猜到,原因在于处理器的有限缓存。我在现代处理器方面真的很差,我真的需要读一读。
不过,我写下这段代码--小白鼠--并掀起这股浪潮,也不是没有原因的。
因此,对于那些正在阅读这个主题的程序员,我将总结一下我个人在这一波中所发现的问题。
我根据这些信息去修改我的代码。我经常滥用数组的大小。
谢谢大家!
我怎么知道十字准星按钮是被按下还是被释放了?
你可以在按下鼠标滚轮时抓取,但如果鼠标不在使用中,你怎么能做到这一点?
我怎么知道十字准星按钮是被按下还是被释放了?
你可以抓住鼠标滚轮的点击,但如果鼠标不在使用中,那怎么办?
在需要的时候强迫它或把它推回去如何?
图表_十字绣_工具
通过按下鼠标中键启用/禁用访问 "十字准线 "工具
bool (默认值为true)
如果有必要,是否可以强制或推倒重来?
图表_十字绣_工具
通过按下鼠标中键来启用/禁用 "十字准线 "工具
bool (默认为真)
据我所知,它只能访问工具,但不能关闭它。