.net - F#中的数组遍历

标签 .net arrays performance f#

在 F# 中迭代​​数组的最快方法是什么?使用 Array.[index] 似乎创建(通过查看 Release 模式下的程序集产品)调用 asm 指令。
有没有办法避免这种情况?
谢谢

120:             me.[i] <- me.[i] ||| you.[i]
    0000005b 8B 45 F8             mov         eax,dword ptr [ebp-8] 
    0000005e 8B 55 E0             mov         edx,dword ptr [ebp-20h] 
    00000061 3B 42 04             cmp         eax,dword ptr [edx+4] 
    00000064 72 05                jb          0000006B 
    00000066 E8 35 CD B9 65       call        65B9CDA0 
    0000006b 8B 4C C2 08          mov         ecx,dword ptr [edx+eax*8+8] 
    0000006f 8B 5C C2 0C          mov         ebx,dword ptr [edx+eax*8+0Ch] 
    00000073 8B 45 F8             mov         eax,dword ptr [ebp-8] 
    00000076 8B 55 DC             mov         edx,dword ptr [ebp-24h] 
    00000079 3B 42 04             cmp         eax,dword ptr [edx+4] 
    0000007c 72 05                jb          00000083 
    0000007e E8 1D CD B9 65       call        65B9CDA0 
    00000083 0B 4C C2 08          or          ecx,dword ptr [edx+eax*8+8] 
    00000087 0B 5C C2 0C          or          ebx,dword ptr [edx+eax*8+0Ch] 
    0000008b 89 4D EC             mov         dword ptr [ebp-14h],ecx 
    0000008e 89 5D F0             mov         dword ptr [ebp-10h],ebx 
    00000091 8B 45 F8             mov         eax,dword ptr [ebp-8] 
    00000094 8B 55 E0             mov         edx,dword ptr [ebp-20h] 
    00000097 3B 42 04             cmp         eax,dword ptr [edx+4] 
    0000009a 72 05                jb          000000A1 
    0000009c E8 FF CC B9 65       call        65B9CDA0 
    000000a1 8B 4D EC             mov         ecx,dword ptr [ebp-14h] 
    000000a4 8B 5D F0             mov         ebx,dword ptr [ebp-10h] 
    000000a7 89 4C C2 08          mov         dword ptr [edx+eax*8+8],ecx 
    000000ab 89 5C C2 0C          mov         dword ptr [edx+eax*8+0Ch],ebx  

更新:使用 Array.iter 给我:
   122:           me |> Array.iteri (fun i elem -> me.[i] <- me.[i] ||| you.[i] )
0000003a B9 18 26 70 00       mov         ecx,702618h 
0000003f E8 7C 53 A5 FF       call        FFA553C0 
00000044 89 45 E0             mov         dword ptr [ebp-20h],eax 
00000047 FF 75 E4             push        dword ptr [ebp-1Ch] 
0000004a 8B 55 E8             mov         edx,dword ptr [ebp-18h] 
0000004d 8B 4D E0             mov         ecx,dword ptr [ebp-20h] 
00000050 FF 15 00 26 70 00    call        dword ptr ds:[00702600h] 
00000056 8B 55 E8             mov         edx,dword ptr [ebp-18h] 
00000059 8B 4D E0             mov         ecx,dword ptr [ebp-20h] 
0000005c 8B 05 DC 27 70 00    mov         eax,dword ptr ds:[007027DCh] 
00000062 6A 00                push        0 
00000064 6A 00                push        0 
00000066 6A 01                push        1 
00000068 50                   push        eax 
00000069 83 3D 88 A2 63 66 00 cmp         dword ptr ds:[6663A288h],0 
00000070 74 09                je          0000007B 
00000072 51                   push        ecx 
00000073 52                   push        edx 
00000074 E8 C2 DE C1 65       call        65C1DF3B 
00000079 5A                   pop         edx 
0000007a 59                   pop         ecx 
0000007b E8 A7 5C 96 65       call        65965D27 
00000080 CC                   int         3 

最佳答案

作为猜测,您在调试器下运行时获得了反汇编的源代码。调试器的存在阻止了许多 JIT 优化。作为演示:

let assign (a : _[]) (b : _[]) =
    for i = 0 to a.Length do
        a.[i] <- b.[i] 
        System.Diagnostics.Trace.Assert(false)
        |> ignore

assign [|1|] [|0|]

使用调试器发布:
        a.[i] <- b.[i] 
0000003b  mov         eax,dword ptr [ebp-8] 
0000003e  mov         edx,dword ptr [ebp-14h] 
00000041  cmp         eax,dword ptr [edx+4] 
00000044  jb          0000004B 
00000046  call        762798A8 
0000004b  mov         eax,dword ptr [edx+eax*4+8] 
0000004f  mov         dword ptr [ebp-0Ch],eax 
00000052  mov         eax,dword ptr [ebp-8] 
00000055  mov         edx,dword ptr [ebp-10h] 
00000058  cmp         eax,dword ptr [edx+4] 
0000005b  jb          00000062 
0000005d  call        762798A8 
00000062  mov         ecx,dword ptr [ebp-0Ch] 
00000065  mov         dword ptr [edx+eax*4+8],ecx 
....

释放,无调试器(使用 ctrl+f5 运行,当 Assert 窗口弹出时按 Retry,然后才将调试器附加到进程中)
        a.[i] <- b.[i] 
00000017  cmp         esi,dword ptr [ebx+4] 
0000001a  jae         00000043 
0000001c  mov         eax,dword ptr [ebx+esi*4+8] 
00000020  cmp         esi,dword ptr [edi+4] 
00000023  jae         00000043 
00000025  mov         dword ptr [edi+esi*4+8],eax 
....

关于.net - F#中的数组遍历,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6535073/

相关文章:

python - Windows 和 Linux 中的 Hashlib

.net - 如何在 CLR 1.1 或 2.0 应用程序中使用 CLR 4.0 组件?

javascript - 使用 Array.prototype.slice.call 的 javascript 出现问题

c# - 判断对象是否为任意类型的数组,并获取数组长度

c++ - 使用动态内存分配将元素添加到数组中

mysql - 将多个长文本放入同一个表 mysql 中是一个好习惯吗?

performance - 提取 DataStage 作业性能统计信息(开始和结束时间)

c# - "arbitrary"分隔符之间的 RegEx 替换

c# - 互联网上的企业数据

.net - AOP 和 .NET : Is Contexts an obsolete concept?