gpt4 book ai didi

c# - 为什么添加局部变量会使 .NET 代码变慢

转载 作者:IT王子 更新时间:2023-10-29 03:54:56 25 4
gpt4 key购买 nike

为什么注释掉此 for 循环的前两行并取消注释第三行会导致 42% 的加速?

int count = 0;
for (uint i = 0; i < 1000000000; ++i) {
var isMultipleOf16 = i % 16 == 0;
count += isMultipleOf16 ? 1 : 0;
//count += i % 16 == 0 ? 1 : 0;
}

时序背后是截然不同的汇编代码:循环中有 13 条指令和 7 条指令。该平台是运行 .NET 4.0 x64 的 Windows 7。代码优化已启用,测试应用程序在 VS2010 之外运行。 [更新: Repro project ,对于验证项目设置很有用。]

消除中间 bool 值是一项基本优化,是我 1980 年代最简单的优化之一 Dragon Book .在生成 CIL 或对 x64 机器代码进行 JIT 时,优化是如何得不到应用的?

是否有“真正的编译器,请您优化这段代码”开关?虽然我同情过早优化类似于 love of money 的观点。 ,我可以看到试图描述一个复杂算法的挫败感,这个算法在其例程中散布着这样的问题。你会在热点中工作,但没有迹象表明可以通过手动调整我们通常认为从编译器中理所当然的东西来大大改善更广泛的温暖区域。我当然希望我在这里遗漏了一些东西。

更新:x86 也存在速度差异,但取决于即时编译方法的顺序。参见 Why does JIT order affect performance?

汇编代码(根据要求):

    var isMultipleOf16 = i % 16 == 0;
00000037 mov eax,edx
00000039 and eax,0Fh
0000003c xor ecx,ecx
0000003e test eax,eax
00000040 sete cl
count += isMultipleOf16 ? 1 : 0;
00000043 movzx eax,cl
00000046 test eax,eax
00000048 jne 0000000000000050
0000004a xor eax,eax
0000004c jmp 0000000000000055
0000004e xchg ax,ax
00000050 mov eax,1
00000055 lea r8d,[rbx+rax]
    count += i % 16 == 0 ? 1 : 0;
00000037 mov eax,ecx
00000039 and eax,0Fh
0000003c je 0000000000000042
0000003e xor eax,eax
00000040 jmp 0000000000000047
00000042 mov eax,1
00000047 lea edx,[rbx+rax]

最佳答案

问题应该是“为什么我在我的机器上看到这样的差异?”。我无法重现如此巨大的速度差异,并怀疑您的环境存在某些特定问题。很难说它可能是什么。可能是您之前设置的一些(编译器)选项,但忘记了它们。

我已经创建了一个控制台应用程序,以 Release模式 (x86) 重建并在 VS 外部运行。两种方法的结果几乎相同,均为 1.77 秒。这是确切的代码:

static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
sw.Start();
int count = 0;

for (uint i = 0; i < 1000000000; ++i)
{
// 1st method
var isMultipleOf16 = i % 16 == 0;
count += isMultipleOf16 ? 1 : 0;

// 2nd method
//count += i % 16 == 0 ? 1 : 0;
}

sw.Stop();
Console.WriteLine(string.Format("Ellapsed {0}, count {1}", sw.Elapsed, count));
Console.ReadKey();
}

请任何有 5 分钟时间的人复制代码、重建、在 VS 之外运行并将结果发布到此答案的评论中。我不想说“它在我的机器上工作”。

编辑

为了确保我已经创建了一个64 位 Winforms 应用程序并且结果与问题中的相似 - 第一种方法比第一种方法慢(1.57 秒)第二个(1.05 秒)。我观察到的差异是 33%——仍然很大。 .NET4 64 位 JIT 编译器中似乎存在错误。

关于c# - 为什么添加局部变量会使 .NET 代码变慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10369421/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com