Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/258.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 这两个代码段中的第一个在做更多工作时如何比第二个快3倍?_C#_Performance_X86_Jit_X86 64 - Fatal编程技术网

C# 这两个代码段中的第一个在做更多工作时如何比第二个快3倍?

C# 这两个代码段中的第一个在做更多工作时如何比第二个快3倍?,c#,performance,x86,jit,x86-64,C#,Performance,X86,Jit,X86 64,此代码如何: var check = 0; for (var numerator = 0; numerator <= maxNumerator; numerator++) { check += numerator >= 0 ? numerator - (int) ((numerator * qdi.Multiplier) >> qdi.Shift) * qdi.Number : numerator - (int) -(

此代码如何:

var check = 0;

for (var numerator = 0; numerator <= maxNumerator; numerator++)
{
    check += numerator >= 0
           ? numerator - (int) ((numerator * qdi.Multiplier) >> qdi.Shift) * qdi.Number
           : numerator - (int) -((-numerator * qdi.Multiplier) >> qdi.Shift) * qdi.Number;
}

return check;
var check = 0;

for (var numerator = 0; numerator <= maxNumerator; numerator++)
{
    check += numerator >= 0
           ? (int) ((numerator * qdi.Multiplier) >> qdi.Shift)
           : (int) -((-numerator * qdi.Multiplier) >> qdi.Shift);
}

return check;
var检查=0;
对于(变量分子=0;分子=0
分子-(int)((分子*量子点乘数)>>量子点移位)*量子点编号
:分子-(int)-(分子*qdi.Multiplier)>>qdi.Shift)*qdi.Number;
}
退货检查;
运行速度比此代码快3倍:

var check = 0;

for (var numerator = 0; numerator <= maxNumerator; numerator++)
{
    check += numerator >= 0
           ? numerator - (int) ((numerator * qdi.Multiplier) >> qdi.Shift) * qdi.Number
           : numerator - (int) -((-numerator * qdi.Multiplier) >> qdi.Shift) * qdi.Number;
}

return check;
var check = 0;

for (var numerator = 0; numerator <= maxNumerator; numerator++)
{
    check += numerator >= 0
           ? (int) ((numerator * qdi.Multiplier) >> qdi.Shift)
           : (int) -((-numerator * qdi.Multiplier) >> qdi.Shift);
}

return check;
var检查=0;
对于(变量分子=0;分子=0
?(int)((分子*量子点乘数)>>量子点移位)
:(int)-((-分子*qdi.乘数)>>qdi.Shift);
}
退货检查;
第一个代码段执行完全相同的快速除法操作(即先乘法,然后右移),但也执行减法和乘法,但JIT编译器似乎生成的代码较慢

我有每个可用的反汇编代码。
较慢的代码推送rbx寄存器,并在开始时从rsp中减去10h,然后将其相加,并在结束时弹出rbx,而较快的代码则没有。
速度较慢的代码在大多数情况下也使用r11寄存器,而速度较快的代码使用rdx


有什么想法吗?

三值运算中使用的条件可能会影响生成的代码

三元优化似乎比简单的if/else生成的代码效率更低

因此,将第二个snippest中的循环代码更改为:

if (numerator >= 0) check += (int) ((numerator * qdi.Multiplier) >> qdi.Shift);
else check += (int) -((-numerator * qdi.Multiplier) >> qdi.Shift);
或:

if(分子<0)check+=(int)-(分子*qdi.Multiplier)>>qdi.Shift);
else check+=(int)((分子*qdi.Multiplier)>>qdi.Shift);
或:

check+=分子<0
?(int)-((-分子*量子点乘数)>>量子点移位)
:(int)((分子*qdi.乘数)>>qdi.Shift);
将生成运行速度更快的代码


事实上,我觉得有点令人不安,四种组合中有三种会产生快速代码,而另一种组合会产生缓慢的代码……有时。

你是如何衡量的?你对汇编语言的描述听起来并不像是会带来巨大性能差异的东西

无论如何,如果它真的慢了很多,我怀疑JIT团队之外的任何人都不能确切地说出发生这种情况的原因。我在进行.NET微基准测试时注意到,看似微不足道的代码更改可能会使代码运行得明显更快或更慢。如果您能够编写代码(这会触发缓慢)尽可能简单,您可以在Microsoft Connect上向MS投诉


您可以尝试复制qdi.Multiplier、qdi.Shift和qdi.Number(无论它们是什么)对于局部变量,这有时会有帮助。

抓住救命稻草,但我想知道这是否与数据宽度有关;JIT在选择如何优化代码时确实考虑了数据的大小。如果使用不安全的块包装任一循环,会发生什么情况?请尝试以相反的顺序运行代码段。是否您遇到缓存问题未命中?我认为这对Raymond Chen来说是一个好问题!哦,另一个想法,它使用R11和RDX,因为它的目标是x64,我相信,如果你专门针对x86,会发生什么?Russ C:代码适用于任何CPU,但我尝试了x64和x86,结果相同;也尝试了不安全-仍然相同。不确定你所说的数据宽度是什么意思-都是int-ex除了乘法器,它是一个长的;在两种情况下都是相同的。史蒂文:已经分别作为单元测试和控制台应用程序运行了它们。始终是一样的。为什么不使用标准运算符进行除法?
QuickDivideInfo struct
的布局是什么?另外,您在不同的机器上看到了相同的行为吗?可以看到代码这里。这里只有一台机器,但很快将用测试代码更新文章,我们将看到!速度确实慢了很多。显示的循环被执行了50次,这是定时的。整个循环被循环了10次,以获得10个不同的计时。在两次传递之间运行一个完整的GC(包括等待待定的终结器)线程优先级设置为高于正常值,以尽可能减少中断。慢速运行时需要约10秒,快速运行时需要约3.2秒。这不是一个平凡的差别。:-)我同意局部变量可以稍微快一点,但这不是本例的重点。编译器应该在所有四种情况下生成相同的代码(?:with>=0;?:with<0;if/then with>=0和if/then with<0)