mql5语言的特点、微妙之处以及技巧 - 页 117 1...110111112113114115116117118119120121122123124...247 新评论 Alexey Navoykov 2019.01.05 05:30 #1161 这是我想出的变体。 int log2_(ulong n) { if (n==0) return -1; #define M(n, i, base, S) ( n >= (ulong(1)<<(i)) ? S(n, i+base/2) : S(n, i-(base+1)/2) ) #define S_0(n, i) i #define S_1(n, i) M(n, i, 1, S_0) #define S_2(n, i) M(n, i, 2, S_1) #define S_4(n, i) M(n, i, 4, S_2) #define S_8(n, i) M(n, i, 8, S_4) #define S_16(n, i) M(n, i, 16, S_8) #define S(n) M(n, 32, 32, S_16) return S(n); } 这应该是所有可能的变量中最快的。 所有的计算都是用常数进行的,所以它们是在编译过程中计算的。 因此,一切都被减少到只有6个连续的比较,而没有其他。 然而,这个变量的工作速度比前一个慢。 我不明白这其中的原因。 Georgiy Merts 2019.01.05 06:37 #1162 Alexey Navoykov:这是我想出的变体。 所有的计算都是用常数进行的,所以它们是在编译过程中计算的。 因此,一切都被简化为6个连续的比较,而不是其他。 然而,这个变体的工作速度比前一个慢。 我不明白原因是什么。除以2会减慢速度?试着用移位来代替? 我怀疑计算的常数--必须立即计算(在这种情况下--定义中的移位--也必须用常数来代替)。 此外,据我所知,"question "是一个相当有争议的操作符,20年前它在C++中被检查过,有时 "question "产生的代码比通常的if操作符长得多。也许这里也是如此? 而且,我会让返回代码变成uint--如果在转换有符号和无符号值时有一些检查怎么办? 我还没有机会进行手动实验--CPU已经超负荷了......。即使是文字也是 "缓慢地 "打出来的...... Alexey Navoykov 2019.01.05 07:05 #1163 Georgiy Merts:除以2的速度减慢?试着用移位来代替它? 我怀疑计算的常数--必须立即计算(在这种情况下--定义中的移位--也必须用常数来代替)。 另外--"问题" --我知道,这是一个相当有争议的操作者...... 用shift代替除法没有效果。 我怀疑产生的表达式太长了,所以编译器没有把它优化到最后。 但我在优化=0时进行了测试,而当优化启用时,一切都很顺利--第二个变体的速度快了1.5倍。中奖了! 如果禁用优化,那么第二个选项在小数值时稍慢,但在大数值时稍快。 总之,第二个选项肯定更好。 Nikolai Semko 2019.01.05 07:31 #1164 Alexey Navoykov:这是我想出的变体。 这据说是所有可能的变体中最快的。 所有的计算都是用常数进行的,所以它们是在编译过程中计算的。 因此,一切都被减少到只有6个连续的比较,而没有其他。 然而,这个变体的工作速度比前一个慢。 我不明白这其中的原因。这就对了--你的变体是最快的。 只是这个测试是闲置的。程序员在测试性能时经常忘记一件重要的事情:如果一个计算值没有在任何地方使用,编译器就不会进行计算。 这是有道理的,有什么意义呢?这就像在量子叠加中。如果没有人看它,为什么月亮要存在。"月亮的存在只是因为一只老鼠在看它吗?"(Albert Einstein)。:)) 因此,这个版本的测试中的校验计算和打印会更正确。 #property strict #define test(M,S,EX) {long sum=0; uint nn=(uint)pow(10,M); ulong mss=GetMicrosecondCount(); for(uint t12=1;t12<=nn;t12++){EX;sum+=(long)n1;} \ Print(S+": loops="+(string)nn+" μs="+string(GetMicrosecondCount()-mss)+" Контрольная сумма="+string(sum));} int log2(ulong n){ if (n==0) return -1; #define S(k) if (n >= (ulong(1)<<k)) { i += k; n >>= k; } int i=0; S(32); S(16); S(8); S(4); S(2); S(1); return i; #undef S} static const uint ulLogTable[64] = { 0, 58, 1, 59, 47, 53, 2, 60, 39, 48, 27, 54, 33, 42, 3, 61, 51, 37, 40, 49, 18, 28, 20, 55, 30, 34, 11, 43, 14, 22, 4, 62, 57, 46, 52, 38, 26, 32, 41, 50, 36, 17, 19, 29, 10, 13, 21, 56, 45, 25, 31, 35, 16, 9, 12, 44, 24, 15, 8, 23, 7, 6, 5, 63 }; uint _FastLog2(ulong ulInput){ ulInput |= ulInput >> 1; ulInput |= ulInput >> 2; ulInput |= ulInput >> 4; ulInput |= ulInput >> 8; ulInput |= ulInput >> 16; ulInput |= ulInput >> 32; return(ulLogTable[(uint)((ulInput * 0x03f6eaf2cd271461) >> 58)]);}; int log2_(ulong n) { if (n==0) return -1; #define M(n, i, base, S) ( n >= (ulong(1)<<(i)) ? S(n, i+base/2) : S(n, i-(base+1)/2) ) #define S_0(n, i) i #define S_1(n, i) M(n, i, 1, S_0) #define S_2(n, i) M(n, i, 2, S_1) #define S_4(n, i) M(n, i, 4, S_2) #define S_8(n, i) M(n, i, 8, S_4) #define S_16(n, i) M(n, i, 16, S_8) #define S(n) M(n, 32, 32, S_16) return S(n); } void OnStart(){ srand(GetTickCount()); ulong n1; test(8,"MathLog",n1=ulong(MathLog((double)t12)/MathLog(2.0))) test(8,"log2",n1=log2(t12)) test(8,"log2_",n1=log2_(t12)) test(8,"_FastLog2",n1=_FastLog2(t12))} 结果。 2019.01.05 02:30:03.681 TestLog (.BrentCrud,H4) MathLog: loops=100000000 μs=805196 Контрольная сумма=2465782300 2019.01.05 02:30:04.092 TestLog (.BrentCrud,H4) log2: loops=100000000 μs=410657 Контрольная сумма=2465782300 2019.01.05 02:30:04.234 TestLog (.BrentCrud,H4) log2_: loops=100000000 μs=141975 Контрольная сумма=2465782300 2019.01.05 02:30:04.432 TestLog (.BrentCrud,H4) _FastLog2: loops=100000000 μs=198015 Контрольная сумма=2465782300 而第二名仍然是_FastLog2,而不是log2 :)) Alexey Navoykov 2019.01.05 08:47 #1165 Nikolai Semko:这只是一个闲置的测试。在性能测试中经常会忘记一个重要的问题:如果计算值没有在任何地方使用,编译器就不会进行计算。 这是有道理的,有什么意义呢?这就像在量子叠加中。如果没有人看它,为什么月亮要存在。"月亮的存在只是因为一只老鼠在看它吗?"(Albert Einstein)。:)) 因此,这个版本的测试,加上校验计算和打印,将更加正确。你的代码很纠结。 定义中使用的变量位于程序代码的另一端--在这样的混乱中进行排序并不方便。 但这不是重点。 重点是你的测试结果不能被认为是可靠的,因为编译器事先知道传入函数的值的算法。 所以它优化了你的测试。你应该用随机数进行计算 。 顺便说一下,为什么你的代码里有srand? 当我看到它时,起初我以为你在使用随机,但实际上你没有。 以下是我的代码。 void OnStart() { Print("OnStart"); srand(GetTickCount()); int count= 50000000; #define TEST(func) { \ ulong sum=0; \ ulong mcscount= GetMicrosecondCount(); \ for (int i=0; i<count; i++) \ sum += func(rand() | rand()<<15); \ Print("Result "+#func+": sum=",sum," time=",(GetMicrosecondCount()-mcscount)/1000," ms"); \ } TEST(log2); TEST(log2_); } Nikolai Semko 2019.01.05 09:13 #1166 Alexey Navoykov:你的代码很混乱。 定义中使用的变量位于程序代码的另一端--在这样的混乱中进行分类是很不方便的。 但这不是重点,重点是你的测试结果不能被认为是可靠的,因为编译器事先知道传入函数的值的算法。 因此它优化了你的测试。你应该用随机数来 计算。 顺便说一下,为什么你的代码里有srand? 当我看到它时,起初我以为你在使用随机,但实际上你没有。 以下是我的代码。 该代码不是我的。我只是调整了一下,删除了rand,以检查相同的校验和,并从循环中删除了相对昂贵的rand函数,但我根本忘记了删除srand。 我返回兰特。你是对的--编译器确实对连续数值的对数之和的循环进行了优化。不过,我很惊讶。我不明白它是如何做到这一点的。也许有什么是我们没有考虑到的。 #property strict #define test(M,S,EX) {srand(45); long sum=0; uint nn=(uint)pow(10,M); ulong mss=GetMicrosecondCount(); for(uint t12=1;t12<=nn;t12++){EX;sum+=(long)n1;} \ Print(S+": loops="+(string)nn+" μs="+string(GetMicrosecondCount()-mss)+" Контрольная сумма="+string(sum));} int log2(ulong n){ if (n==0) return -1; #define S(k) if (n >= (ulong(1)<<k)) { i += k; n >>= k; } int i=0; S(32); S(16); S(8); S(4); S(2); S(1); return i; #undef S} static const uint ulLogTable[64] = { 0, 58, 1, 59, 47, 53, 2, 60, 39, 48, 27, 54, 33, 42, 3, 61, 51, 37, 40, 49, 18, 28, 20, 55, 30, 34, 11, 43, 14, 22, 4, 62, 57, 46, 52, 38, 26, 32, 41, 50, 36, 17, 19, 29, 10, 13, 21, 56, 45, 25, 31, 35, 16, 9, 12, 44, 24, 15, 8, 23, 7, 6, 5, 63 }; uint _FastLog2(ulong ulInput){ ulInput |= ulInput >> 1; ulInput |= ulInput >> 2; ulInput |= ulInput >> 4; ulInput |= ulInput >> 8; ulInput |= ulInput >> 16; ulInput |= ulInput >> 32; return(ulLogTable[(uint)((ulInput * 0x03f6eaf2cd271461) >> 58)]);}; int log2_(ulong n) { if (n==0) return -1; #define M(n, i, base, S) ( n >= (ulong(1)<<(i)) ? S(n, i+base/2) : S(n, i-(base+1)/2) ) #define S_0(n, i) i #define S_1(n, i) M(n, i, 1, S_0) #define S_2(n, i) M(n, i, 2, S_1) #define S_4(n, i) M(n, i, 4, S_2) #define S_8(n, i) M(n, i, 8, S_4) #define S_16(n, i) M(n, i, 16, S_8) #define S(n) M(n, 32, 32, S_16) return S(n); } void OnStart(){ ulong n1,n; test(8,"MathLog",n=(rand()+1)*(rand()+1);n1=ulong(MathLog((double)n)/MathLog(2.0))) test(8,"log2",n=(rand()+1)*(rand()+1);n1=log2(n)) test(8,"log2_",n=(rand()+1)*(rand()+1);n1=log2_(n)) test(8,"_FastLog2",n=(rand()+1)*(rand()+1);n1=_FastLog2(n))} 结果。 2019.01.05 04:10:25.808 TestLog (EURUSD,H1) MathLog: loops=100000000 μs=1168737 Контрольная сумма=2661391201 2019.01.05 04:10:26.474 TestLog (EURUSD,H1) log2: loops=100000000 μs=665631 Контрольная сумма=2661391201 2019.01.05 04:10:27.315 TestLog (EURUSD,H1) log2_: loops=100000000 μs=841299 Контрольная сумма=2661391201 2019.01.05 04:10:27.694 TestLog (EURUSD,H1) _FastLog2: loops=100000000 μs=378627 Контрольная сумма=2661391201 目前的冠军是_FastLog2 Alexey Navoykov 2019.01.05 09:22 #1167 Nikolai Semko:结果。 目前的赢家 _FastLog2我想知道,如果数值是随机的,你是如何在所有地方得到相同的校验和的。 Nikolai Semko 2019.01.05 09:25 #1168 Alexey Navoykov:我想知道,如果数值是随机的,你是如何在所有地方得到相同的校验和的。srand(45)的所有函数 我一开始也是这样做的,但得到的校验和不同,因为我没有考虑到rand()*rand()可能是0,这就破坏了校验和。现在我加了一个,以摆脱零。 Alexey Navoykov 2019.01.05 09:30 #1169 Nikolai Semko:srand(45)的所有函数 我一开始也是这么做的,但得到的校验和不同,因为我没有考虑到rand()*rand()可以为0,这就破坏了校验和。现在我加了一个,以摆脱零。如果我们专门讨论速度测量,为什么需要同样的校验呢? 在这种情况下,和的意义只是为了防止编译器切割代码,仅此而已。 而通过做srand(45),你又允许优化测试。 顺便说一下,说到零,FastLog2不检查零,这给了它一个先机。但如果测试正确,它仍然比log2慢1.5到2倍)。 Nikolai Semko 2019.01.05 09:38 #1170 Alexey Navoykov: 如果我们专门讨论速度测量,为什么需要同样的校验? 在这种情况下,和的意义只是为了防止编译器切割代码,仅此而已。 而做srand(45),又可以让你优化测试。你在这里高估了编译器的能力。删除srand(45)--校验和会有所不同,但速度结果仍然是一样的。 此外,我的指导思想是,为了实验的纯洁性,计算结果是一样的,因为我没有深入研究所有函数的细节。有时,一个函数参数的值会影响其执行的时间。 所以更有理由检查算法的正确性。 1...110111112113114115116117118119120121122123124...247 新评论 您错过了交易机会: 免费交易应用程序 8,000+信号可供复制 探索金融市场的经济新闻 注册 登录 拉丁字符(不带空格) 密码将被发送至该邮箱 发生错误 使用 Google 登录 您同意网站政策和使用条款 如果您没有帐号,请注册 可以使用cookies登录MQL5.com网站。 请在您的浏览器中启用必要的设置,否则您将无法登录。 忘记您的登录名/密码? 使用 Google 登录
这是我想出的变体。
这应该是所有可能的变量中最快的。 所有的计算都是用常数进行的,所以它们是在编译过程中计算的。 因此,一切都被减少到只有6个连续的比较,而没有其他。 然而,这个变量的工作速度比前一个慢。 我不明白这其中的原因。
这是我想出的变体。
所有的计算都是用常数进行的,所以它们是在编译过程中计算的。 因此,一切都被简化为6个连续的比较,而不是其他。 然而,这个变体的工作速度比前一个慢。 我不明白原因是什么。
除以2会减慢速度?试着用移位来代替? 我怀疑计算的常数--必须立即计算(在这种情况下--定义中的移位--也必须用常数来代替)。
此外,据我所知,"question "是一个相当有争议的操作符,20年前它在C++中被检查过,有时 "question "产生的代码比通常的if操作符长得多。也许这里也是如此?
而且,我会让返回代码变成uint--如果在转换有符号和无符号值时有一些检查怎么办?
我还没有机会进行手动实验--CPU已经超负荷了......。即使是文字也是 "缓慢地 "打出来的......
除以2的速度减慢?试着用移位来代替它? 我怀疑计算的常数--必须立即计算(在这种情况下--定义中的移位--也必须用常数来代替)。
另外--"问题" --我知道,这是一个相当有争议的操作者......
用shift代替除法没有效果。 我怀疑产生的表达式太长了,所以编译器没有把它优化到最后。
但我在优化=0时进行了测试,而当优化启用时,一切都很顺利--第二个变体的速度快了1.5倍。中奖了!
如果禁用优化,那么第二个选项在小数值时稍慢,但在大数值时稍快。 总之,第二个选项肯定更好。
这是我想出的变体。
这据说是所有可能的变体中最快的。 所有的计算都是用常数进行的,所以它们是在编译过程中计算的。 因此,一切都被减少到只有6个连续的比较,而没有其他。 然而,这个变体的工作速度比前一个慢。 我不明白这其中的原因。
这就对了--你的变体是最快的。
只是这个测试是闲置的。程序员在测试性能时经常忘记一件重要的事情:如果一个计算值没有在任何地方使用,编译器就不会进行计算。
这是有道理的,有什么意义呢?这就像在量子叠加中。如果没有人看它,为什么月亮要存在。"月亮的存在只是因为一只老鼠在看它吗?"(Albert Einstein)。:))
因此,这个版本的测试中的校验计算和打印会更正确。
结果。
而第二名仍然是_FastLog2,而不是log2 :))这只是一个闲置的测试。在性能测试中经常会忘记一个重要的问题:如果计算值没有在任何地方使用,编译器就不会进行计算。
这是有道理的,有什么意义呢?这就像在量子叠加中。如果没有人看它,为什么月亮要存在。"月亮的存在只是因为一只老鼠在看它吗?"(Albert Einstein)。:))
因此,这个版本的测试,加上校验计算和打印,将更加正确。
你的代码很纠结。 定义中使用的变量位于程序代码的另一端--在这样的混乱中进行排序并不方便。 但这不是重点。 重点是你的测试结果不能被认为是可靠的,因为编译器事先知道传入函数的值的算法。 所以它优化了你的测试。你应该用随机数进行计算 。
顺便说一下,为什么你的代码里有srand? 当我看到它时,起初我以为你在使用随机,但实际上你没有。
以下是我的代码。
你的代码很混乱。 定义中使用的变量位于程序代码的另一端--在这样的混乱中进行分类是很不方便的。 但这不是重点,重点是你的测试结果不能被认为是可靠的,因为编译器事先知道传入函数的值的算法。 因此它优化了你的测试。你应该用随机数来 计算。
顺便说一下,为什么你的代码里有srand? 当我看到它时,起初我以为你在使用随机,但实际上你没有。
以下是我的代码。
该代码不是我的。我只是调整了一下,删除了rand,以检查相同的校验和,并从循环中删除了相对昂贵的rand函数,但我根本忘记了删除srand。
我返回兰特。你是对的--编译器确实对连续数值的对数之和的循环进行了优化。不过,我很惊讶。我不明白它是如何做到这一点的。也许有什么是我们没有考虑到的。
结果。
目前的冠军是_FastLog2
结果。
目前的赢家 _FastLog2
我想知道,如果数值是随机的,你是如何在所有地方得到相同的校验和的。
我想知道,如果数值是随机的,你是如何在所有地方得到相同的校验和的。
srand(45)的所有函数
我一开始也是这样做的,但得到的校验和不同,因为我没有考虑到rand()*rand()可能是0,这就破坏了校验和。现在我加了一个,以摆脱零。
srand(45)的所有函数
我一开始也是这么做的,但得到的校验和不同,因为我没有考虑到rand()*rand()可以为0,这就破坏了校验和。现在我加了一个,以摆脱零。
如果我们专门讨论速度测量,为什么需要同样的校验呢? 在这种情况下,和的意义只是为了防止编译器切割代码,仅此而已。 而通过做srand(45),你又允许优化测试。
顺便说一下,说到零,FastLog2不检查零,这给了它一个先机。但如果测试正确,它仍然比log2慢1.5到2倍)。
如果我们专门讨论速度测量,为什么需要同样的校验? 在这种情况下,和的意义只是为了防止编译器切割代码,仅此而已。 而做srand(45),又可以让你优化测试。
你在这里高估了编译器的能力。删除srand(45)--校验和会有所不同,但速度结果仍然是一样的。
此外,我的指导思想是,为了实验的纯洁性,计算结果是一样的,因为我没有深入研究所有函数的细节。有时,一个函数参数的值会影响其执行的时间。
所以更有理由检查算法的正确性。