xxx_numba_parfor_gufunc_xxx 函数。这个最后一个函数执行并行循环的内容。调用者函数对于两种实现都是相同的。两个版本的主要计算函数不同。以下是我的机器上的汇编代码:
----- WITHOUT VIEWS -----
_ZN13_3cdynamic_3e40__numba_parfor_gufunc_0x272d183ed00_2487B104c8tJTC_2fWQAkyW1xhBopo9CCDiCFCDMJHDTCIGCy8IDxIcEFloKEF4UEDC8KBhhWIo6mjgJZwoWpwJVOYNCIkbcG2Ai0vgkhqAgA_3dE5ArrayIyLi1E1C7mutable7alignedE23Literal_5bint_5d_283_29x5ArrayIdLi2E1C7mutable7alignedE:
.cfi_startproc
pushq %r15
.cfi_def_cfa_offset 16
pushq %r14
.cfi_def_cfa_offset 24
pushq %r13
.cfi_def_cfa_offset 32
pushq %r12
.cfi_def_cfa_offset 40
pushq %rsi
.cfi_def_cfa_offset 48
pushq %rdi
.cfi_def_cfa_offset 56
pushq %rbp
.cfi_def_cfa_offset 64
pushq %rbx
.cfi_def_cfa_offset 72
subq $280, %rsp
vmovaps %xmm6, 256(%rsp)
.cfi_def_cfa_offset 352
.cfi_offset %rbx, -72
.cfi_offset %rbp, -64
.cfi_offset %rdi, -56
.cfi_offset %rsi, -48
.cfi_offset %r12, -40
.cfi_offset %r13, -32
.cfi_offset %r14, -24
.cfi_offset %r15, -16
.cfi_offset %xmm6, -96
movq %rdx, 160(%rsp)
movq %rcx, 200(%rsp)
movq 504(%rsp), %r14
movq 488(%rsp), %r15
leaq -1(%r15), %rax
imulq %r14, %rax
xorl %ebp, %ebp
testq %rax, %rax
movq %rax, %rdx
cmovnsq %rbp, %rdx
cmpq $1, %r15
cmovbq %rbp, %rdx
movq %rdx, 240(%rsp)
movq %rax, %rdx
sarq $63, %rdx
andnq %rax, %rdx, %rax
addq 464(%rsp), %rax
movq %r15, %rbx
subq $1, %rbx
movq 440(%rsp), %rcx
movq 400(%rsp), %rsi
movabsq $NRT_incref, %rdx
cmovbq %rbp, %rax
movq %rax, 232(%rsp)
callq *%rdx
movq (%rsi), %rbp
movq 8(%rsi), %rdi
subq %rbp, %rdi
incq %rdi
movabsq $NRT_MemInfo_alloc_safe_aligned, %rsi
movl $24, %ecx
movl $32, %edx
callq *%rsi
movq %rax, 192(%rsp)
movq 24(%rax), %rax
movq %rax, 120(%rsp)
movl $24, %ecx
movl $32, %edx
callq *%rsi
movq %rax, 64(%rsp)
testq %rdi, %rdi
jle .LBB6_48
movq %rdi, %r11
movq %rbp, %r8
movq %rbx, %r10
movq %r15, %r9
movq 432(%rsp), %rdx
movq 472(%rsp), %rdi
movq %r15, %rax
imulq 464(%rsp), %rax
movq %rax, 208(%rsp)
xorl %eax, %eax
testq %rdx, %rdx
setg %al
movq %rdx, %rcx
sarq $63, %rcx
andnq %rdx, %rcx, %rcx
subq %rax, %rcx
movq %rcx, 224(%rsp)
leaq -4(%r15), %rax
movq %rax, 184(%rsp)
shrq $2, %rax
incq %rax
andl $7, %r15d
movq %r9, %r13
andq $-8, %r13
movq %r9, %rcx
andq $-4, %rcx
movq %rcx, 176(%rsp)
movl %eax, %ecx
andl $7, %ecx
movq %rbp, %rdx
imulq %r9, %rdx
movq %rcx, 168(%rsp)
shlq $5, %rcx
movq %rcx, 152(%rsp)
andq $-8, %rax
addq $-8, %rax
movq %rax, 144(%rsp)
movq %rax, %rcx
shrq $3, %rcx
incq %rcx
movq %rcx, %rax
movq %rcx, 136(%rsp)
andq $-2, %rcx
movq %rcx, 128(%rsp)
vxorps %xmm6, %xmm6, %xmm6
movq 64(%rsp), %rax
movq 24(%rax), %rax
movq %rax, 248(%rsp)
leaq 56(%rdi,%rdx,8), %rsi
leaq 224(%rdi,%rdx,8), %rcx
leaq (,%r9,8), %rax
movq %rax, 88(%rsp)
leaq (%rdi,%rdx,8), %rax
addq $480, %rax
movq %rax, 80(%rsp)
xorl %eax, %eax
movq %rax, 96(%rsp)
movq %rdx, 216(%rsp)
movq %rdx, 112(%rsp)
movq %rbx, 56(%rsp)
jmp .LBB6_3
.p2align 4, 0x90
.LBB6_2:
leaq -1(%r11), %rax
incq %r8
addq %r9, 112(%rsp)
movq 104(%rsp), %rcx
leaq (%rcx,%r9,8), %rcx
incq 96(%rsp)
movq 88(%rsp), %rdx
addq %rdx, %rsi
addq %rdx, 80(%rsp)
cmpq $2, %r11
movq %rax, %r11
jl .LBB6_48
.LBB6_3:
movq %rcx, 104(%rsp)
movq %r8, %rax
imulq %r9, %rax
movq 472(%rsp), %rdi
leaq (%rdi,%rax,8), %rbp
movq 240(%rsp), %rax
addq %rbp, %rax
movq 232(%rsp), %rcx
addq %rbp, %rcx
movq %r8, %rdx
imulq 496(%rsp), %rdx
movq 464(%rsp), %rbx
addq %rdx, %rbx
testq %r9, %r9
cmoveq %r9, %rdx
cmoveq %r9, %rbx
addq %rdi, %rdx
addq %rdi, %rbx
cmpq %rbx, %rax
setb 39(%rsp)
cmpq %rcx, %rdx
setb %al
cmpq $0, 432(%rsp)
jle .LBB6_2
cmpq 424(%rsp), %r9
jne .LBB6_46
movq 96(%rsp), %rcx
imulq %r9, %rcx
addq 216(%rsp), %rcx
andb %al, 39(%rsp)
movq 472(%rsp), %rax
leaq (%rax,%rcx,8), %rax
movq %rax, 72(%rsp)
movl $1, %eax
movq 224(%rsp), %rbx
xorl %r12d, %r12d
.p2align 4, 0x90
.LBB6_6:
imulq %r8, %r12
vcvtsi2sd %r12, %xmm2, %xmm0
vsqrtsd %xmm0, %xmm0, %xmm0
movq 120(%rsp), %rcx
vmovups %xmm6, (%rcx)
movq $0, 16(%rcx)
movq 248(%rsp), %rdx
vmovsd %xmm0, (%rdx)
vaddsd (%rbp), %xmm0, %xmm1
vmovsd %xmm1, (%rbp)
vaddsd 8(%rcx), %xmm0, %xmm1
vmovsd %xmm1, 8(%rdx)
vaddsd 8(%rbp), %xmm1, %xmm1
vmovsd %xmm1, 8(%rbp)
vaddsd 16(%rcx), %xmm0, %xmm0
vmovsd %xmm0, 16(%rdx)
movq %rax, %r12
vaddsd 16(%rbp), %xmm0, %xmm0
vmovsd %xmm0, 16(%rbp)
cmpb $0, 39(%rsp)
jne .LBB6_7
testq %r9, %r9
jle .LBB6_28
cmpq $7, %r10
jae .LBB6_19
xorl %eax, %eax
movq %rbp, %rdi
testq %r15, %r15
jne .LBB6_23
jmp .LBB6_26
.p2align 4, 0x90
.LBB6_19:
movq %rbp, %rcx
xorl %eax, %eax
.p2align 4, 0x90
.LBB6_20:
movq (%rcx), %rdx
movq %rdx, -56(%rsi,%rax,8)
leaq (%r14,%rcx), %rdx
movq (%r14,%rcx), %rcx
movq %rcx, -48(%rsi,%rax,8)
leaq (%r14,%rdx), %rcx
movq (%r14,%rdx), %rdx
movq %rdx, -40(%rsi,%rax,8)
leaq (%r14,%rcx), %rdx
movq (%r14,%rcx), %rcx
movq %rcx, -32(%rsi,%rax,8)
leaq (%r14,%rdx), %rcx
movq (%r14,%rdx), %rdx
movq %rdx, -24(%rsi,%rax,8)
leaq (%r14,%rcx), %rdx
movq (%r14,%rcx), %rcx
movq %rcx, -16(%rsi,%rax,8)
leaq (%r14,%rdx), %rdi
movq (%r14,%rdx), %rcx
movq %rcx, -8(%rsi,%rax,8)
leaq (%r14,%rdi), %rcx
movq (%r14,%rdi), %rdx
movq %rdx, (%rsi,%rax,8)
addq $8, %rax
addq %r14, %rcx
cmpq %rax, %r13
jne .LBB6_20
movq %r13, %rax
movq %rbp, %rdi
testq %r15, %r15
je .LBB6_26
.LBB6_23:
movq 112(%rsp), %rcx
addq %rax, %rcx
imulq %r14, %rax
addq %rbp, %rax
movq 472(%rsp), %rdx
leaq (%rdx,%rcx,8), %rcx
xorl %edx, %edx
.p2align 4, 0x90
.LBB6_24:
movq (%rax), %rdi
movq %rdi, (%rcx,%rdx,8)
incq %rdx
addq %r14, %rax
cmpq %rdx, %r15
jne .LBB6_24
movq %rbp, %rdi
.LBB6_26:
cmpb $0, 39(%rsp)
jne .LBB6_27
.LBB6_28:
xorl %eax, %eax
testq %rbx, %rbx
setg %al
movq %rbx, %rcx
subq %rax, %rcx
addq %r12, %rax
testq %rbx, %rbx
movq %rcx, %rbx
jg .LBB6_6
jmp .LBB6_2
.LBB6_7:
movq %r11, 48(%rsp)
movq %r8, 40(%rsp)
movq 208(%rsp), %rcx
movabsq $NRT_Allocate, %rax
vzeroupper
callq *%rax
movq 488(%rsp), %r9
movq %rax, %rdi
testq %r9, %r9
jle .LBB6_8
movq 56(%rsp), %r10
cmpq $7, %r10
movq 48(%rsp), %r11
jae .LBB6_11
xorl %eax, %eax
testq %r15, %r15
jne .LBB6_15
jmp .LBB6_17
.LBB6_8:
movq 40(%rsp), %r8
movq 48(%rsp), %r11
.LBB6_27:
movq %r8, 40(%rsp)
movq %rdi, %rcx
movq %r11, %rdi
movabsq $NRT_Free, %rax
vzeroupper
callq *%rax
movq %rdi, %r11
movq 40(%rsp), %r8
movq 56(%rsp), %r10
movq 488(%rsp), %r9
jmp .LBB6_28
.LBB6_11:
movq %rbp, %rcx
xorl %eax, %eax
.p2align 4, 0x90
.LBB6_12:
movq (%rcx), %rdx
movq %rdx, (%rdi,%rax,8)
leaq (%r14,%rcx), %rdx
movq (%r14,%rcx), %rcx
movq %rcx, 8(%rdi,%rax,8)
leaq (%r14,%rdx), %rcx
movq (%r14,%rdx), %rdx
movq %rdx, 16(%rdi,%rax,8)
leaq (%r14,%rcx), %rdx
movq (%r14,%rcx), %rcx
movq %rcx, 24(%rdi,%rax,8)
leaq (%r14,%rdx), %rcx
movq (%r14,%rdx), %rdx
movq %rdx, 32(%rdi,%rax,8)
leaq (%r14,%rcx), %rdx
movq (%r14,%rcx), %rcx
movq %rcx, 40(%rdi,%rax,8)
leaq (%r14,%rdx), %r8
movq (%r14,%rdx), %rcx
movq %rcx, 48(%rdi,%rax,8)
leaq (%r14,%r8), %rcx
movq (%r14,%r8), %rdx
movq %rdx, 56(%rdi,%rax,8)
addq $8, %rax
addq %r14, %rcx
cmpq %rax, %r13
jne .LBB6_12
movq %r13, %rax
testq %r15, %r15
je .LBB6_17
.LBB6_15:
leaq (%rdi,%rax,8), %r8
imulq %r14, %rax
addq %rbp, %rax
xorl %edx, %edx
.p2align 4, 0x90
.LBB6_16:
movq (%rax), %rcx
movq %rcx, (%r8,%rdx,8)
incq %rdx
addq %r14, %rax
cmpq %rdx, %r15
jne .LBB6_16
.LBB6_17:
testq %r9, %r9
jle .LBB6_18
cmpq $3, %r9
movq 40(%rsp), %r8
ja .LBB6_32
xorl %eax, %eax
jmp .LBB6_31
.LBB6_32:
cmpq $28, 184(%rsp)
jae .LBB6_34
xorl %eax, %eax
jmp .LBB6_40
.LBB6_34:
cmpq $0, 144(%rsp)
je .LBB6_35
movq 128(%rsp), %rcx
xorl %eax, %eax
movq 80(%rsp), %rdx
.p2align 4, 0x90
.LBB6_37:
vmovups (%rdi,%rax,8), %ymm0
vmovups %ymm0, -480(%rdx,%rax,8)
vmovups 32(%rdi,%rax,8), %ymm0
vmovups %ymm0, -448(%rdx,%rax,8)
vmovups 64(%rdi,%rax,8), %ymm0
vmovups %ymm0, -416(%rdx,%rax,8)
vmovups 96(%rdi,%rax,8), %ymm0
vmovups %ymm0, -384(%rdx,%rax,8)
vmovups 128(%rdi,%rax,8), %ymm0
vmovups %ymm0, -352(%rdx,%rax,8)
vmovups 160(%rdi,%rax,8), %ymm0
vmovups %ymm0, -320(%rdx,%rax,8)
vmovups 192(%rdi,%rax,8), %ymm0
vmovups %ymm0, -288(%rdx,%rax,8)
vmovups 224(%rdi,%rax,8), %ymm0
vmovups %ymm0, -256(%rdx,%rax,8)
vmovups 256(%rdi,%rax,8), %ymm0
vmovups %ymm0, -224(%rdx,%rax,8)
vmovups 288(%rdi,%rax,8), %ymm0
vmovups %ymm0, -192(%rdx,%rax,8)
vmovups 320(%rdi,%rax,8), %ymm0
vmovups %ymm0, -160(%rdx,%rax,8)
vmovups 352(%rdi,%rax,8), %ymm0
vmovups %ymm0, -128(%rdx,%rax,8)
vmovups 384(%rdi,%rax,8), %ymm0
vmovups %ymm0, -96(%rdx,%rax,8)
vmovups 416(%rdi,%rax,8), %ymm0
vmovups %ymm0, -64(%rdx,%rax,8)
vmovups 448(%rdi,%rax,8), %ymm0
vmovups %ymm0, -32(%rdx,%rax,8)
vmovupd 480(%rdi,%rax,8), %ymm0
vmovupd %ymm0, (%rdx,%rax,8)
addq $64, %rax
addq $-2, %rcx
jne .LBB6_37
testb $1, 136(%rsp)
je .LBB6_40
.LBB6_39:
vmovups (%rdi,%rax,8), %ymm0
movq 104(%rsp), %rcx
vmovups %ymm0, -224(%rcx,%rax,8)
vmovups 32(%rdi,%rax,8), %ymm0
vmovups %ymm0, -192(%rcx,%rax,8)
vmovups 64(%rdi,%rax,8), %ymm0
vmovups %ymm0, -160(%rcx,%rax,8)
vmovups 96(%rdi,%rax,8), %ymm0
vmovups %ymm0, -128(%rcx,%rax,8)
vmovups 128(%rdi,%rax,8), %ymm0
vmovups %ymm0, -96(%rcx,%rax,8)
vmovups 160(%rdi,%rax,8), %ymm0
vmovups %ymm0, -64(%rcx,%rax,8)
vmovups 192(%rdi,%rax,8), %ymm0
vmovups %ymm0, -32(%rcx,%rax,8)
vmovupd 224(%rdi,%rax,8), %ymm0
vmovupd %ymm0, (%rcx,%rax,8)
addq $32, %rax
.LBB6_40:
cmpq $0, 168(%rsp)
je .LBB6_42
movq 72(%rsp), %rcx
leaq (%rcx,%rax,8), %rcx
leaq (%rdi,%rax,8), %rdx
movq 152(%rsp), %r8
movabsq $memcpy, %rax
vzeroupper
callq *%rax
movq 48(%rsp), %r11
movq 40(%rsp), %r8
movq 488(%rsp), %r9
.LBB6_42:
movq 176(%rsp), %rcx
movq %rcx, %rax
cmpq %r9, %rcx
movq 56(%rsp), %r10
je .LBB6_26
.LBB6_31:
movq 72(%rsp), %rcx
leaq (%rcx,%rax,8), %rcx
leaq (%rdi,%rax,8), %rdx
shlq $3, %rax
movq 88(%rsp), %r8
subq %rax, %r8
movabsq $memcpy, %rax
vzeroupper
callq *%rax
movq 48(%rsp), %r11
movq 40(%rsp), %r8
movq 56(%rsp), %r10
movq 488(%rsp), %r9
jmp .LBB6_26
.LBB6_35:
xorl %eax, %eax
testb $1, 136(%rsp)
jne .LBB6_39
jmp .LBB6_40
.LBB6_18:
movq 40(%rsp), %r8
jmp .LBB6_26
.LBB6_48:
movabsq $NRT_decref, %rsi
movq 440(%rsp), %rcx
vzeroupper
callq *%rsi
movq 192(%rsp), %rcx
callq *%rsi
movq 64(%rsp), %rcx
callq *%rsi
movq 200(%rsp), %rax
movq $0, (%rax)
xorl %eax, %eax
jmp .LBB6_47
.LBB6_46:
vxorps %xmm0, %xmm0, %xmm0
movq 120(%rsp), %rax
vmovups %xmm0, (%rax)
movq $0, 16(%rax)
movq 440(%rsp), %rcx
movabsq $NRT_incref, %rax
vzeroupper
callq *%rax
movabsq $.const.picklebuf.2691622873664, %rax
movq 160(%rsp), %rcx
movq %rax, (%rcx)
movl $1, %eax
.LBB6_47:
vmovaps 256(%rsp), %xmm6
addq $280, %rsp
popq %rbx
popq %rbp
popq %rdi
popq %rsi
popq %r12
popq %r13
popq %r14
popq %r15
retq
.Lfunc_end6:
.size _ZN13_3cdynamic_3e40__numba_parfor_gufunc_0x272d183ed00_2487B104c8tJTC_2fWQAkyW1xhBopo9CCDiCFCDMJHDTCIGCy8IDxIcEFloKEF4UEDC8KBhhWIo6mjgJZwoWpwJVOYNCIkbcG2Ai0vgkhqAgA_3dE5ArrayIyLi1E1C7mutable7alignedE23Literal_5bint_5d_283_29x5ArrayIdLi2E1C7mutable7alignedE, .Lfunc_end6-_ZN13_3cdynamic_3e40__numba_parfor_gufunc_0x272d183ed00_2487B104c8tJTC_2fWQAkyW1xhBopo9CCDiCFCDMJHDTCIGCy8IDxIcEFloKEF4UEDC8KBhhWIo6mjgJZwoWpwJVOYNCIkbcG2Ai0vgkhqAgA_3dE5ArrayIyLi1E1C7mutable7alignedE23Literal_5bint_5d_283_29x5ArrayIdLi2E1C7mutable7alignedE
.cfi_endproc
.weak NRT_incref
.p2align 4, 0x90
.type NRT_incref,@function
NRT_incref:
testq %rcx, %rcx
je .LBB7_1
lock incq (%rcx)
retq
.LBB7_1:
retq
.Lfunc_end7:
----- WITH VIEWS -----
__gufunc__._ZN13_3cdynamic_3e40__numba_parfor_gufunc_0x272bef6ed00_2491B104c8tJTC_2fWQAkyW1xhBopo9CCDiCFCDMJHDTCIGCy8IDxIcEFloKEF4UEDC8KBhhWIo6mjgJZwoWpwJVOYNCIkbcG2Ai0vgkhqAgA_3dE5ArrayIyLi1E1C7mutable7alignedE23Literal_5bint_5d_283_29x5ArrayIdLi2E1C7mutable7alignedE:
.cfi_startproc
pushq %r15
.cfi_def_cfa_offset 16
pushq %r14
.cfi_def_cfa_offset 24
pushq %r13
.cfi_def_cfa_offset 32
pushq %r12
.cfi_def_cfa_offset 40
pushq %rsi
.cfi_def_cfa_offset 48
pushq %rdi
.cfi_def_cfa_offset 56
pushq %rbp
.cfi_def_cfa_offset 64
pushq %rbx
.cfi_def_cfa_offset 72
subq $168, %rsp
vmovaps %xmm6, 144(%rsp)
.cfi_def_cfa_offset 240
.cfi_offset %rbx, -72
.cfi_offset %rbp, -64
.cfi_offset %rdi, -56
.cfi_offset %rsi, -48
.cfi_offset %r12, -40
.cfi_offset %r13, -32
.cfi_offset %r14, -24
.cfi_offset %r15, -16
.cfi_offset %xmm6, -96
movq (%rdx), %rax
movq 24(%rdx), %r12
movq (%rcx), %rdx
movq %rdx, 120(%rsp)
movq 8(%rcx), %rdx
movq %rdx, 112(%rsp)
movq (%r8), %rdx
movq %rdx, 104(%rsp)
movq 8(%r8), %rdx
movq %rdx, 96(%rsp)
movq 16(%rcx), %rdx
movq %rdx, 88(%rsp)
movq 16(%r8), %rdx
movq %rdx, 80(%rsp)
movq 24(%rcx), %rcx
movq %rcx, 64(%rsp)
movq 24(%r8), %rcx
movq %rcx, 56(%rsp)
movl $0, 36(%rsp)
movq %rax, 72(%rsp)
testq %rax, %rax
jle .LBB5_12
cmpq $4, %r12
movl $3, %eax
cmovlq %r12, %rax
movq %rax, 48(%rsp)
movq %r12, %rbx
sarq $63, %rbx
andq %r12, %rbx
xorl %eax, %eax
vxorps %xmm6, %xmm6, %xmm6
jmp .LBB5_2
.p2align 4, 0x90
.LBB5_9:
movq 136(%rsp), %rcx
movabsq $NRT_decref, %rsi
movq %r9, %rdi
callq *%rsi
movq %rdi, %rcx
callq *%rsi
movq 40(%rsp), %rax
incq %rax
cmpq 72(%rsp), %rax
je .LBB5_12
.LBB5_2:
movq %rax, %rbp
imulq 104(%rsp), %rbp
movq %rax, %rcx
imulq 96(%rsp), %rcx
movq 112(%rsp), %rdx
movq (%rdx,%rcx), %rcx
movq %rcx, 128(%rsp)
movq %rax, 40(%rsp)
movq %rax, %rcx
imulq 80(%rsp), %rcx
movq 88(%rsp), %rdx
movq (%rdx,%rcx), %rdi
movq 120(%rsp), %rcx
movq (%rbp,%rcx), %r13
movq 8(%rbp,%rcx), %r14
subq %r13, %r14
incq %r14
movl $24, %ecx
movl $32, %edx
movabsq $NRT_MemInfo_alloc_safe_aligned, %rsi
callq *%rsi
movq %rax, 136(%rsp)
movq 24(%rax), %r15
movl $24, %ecx
movl $32, %edx
callq *%rsi
movq %rax, %r9
testq %r14, %r14
jle .LBB5_9
xorl %edx, %edx
testq %rdi, %rdi
setg %r8b
testq %rdi, %rdi
jle .LBB5_9
movq 128(%rsp), %rax
cmpq %rax, 48(%rsp)
jne .LBB5_10
movq 40(%rsp), %rax
imulq 56(%rsp), %rax
addq 64(%rsp), %rax
movq 24(%r9), %rcx
movb %r8b, %dl
negq %rdx
leaq (%rdi,%rdx), %rsi
incq %rsi
.p2align 4, 0x90
.LBB5_6:
movq %r13, %rdi
imulq %r12, %rdi
addq %rbx, %rdi
movq %rsi, %rdx
xorl %ebp, %ebp
.p2align 4, 0x90
.LBB5_7:
vcvtsi2sd %rbp, %xmm2, %xmm0
vsqrtsd %xmm0, %xmm0, %xmm0
vmovups %xmm6, (%r15)
movq $0, 16(%r15)
vmovsd %xmm0, (%rcx)
vaddsd (%rax,%rdi,8), %xmm0, %xmm1
vmovsd %xmm1, (%rax,%rdi,8)
vaddsd 8(%r15), %xmm0, %xmm1
vmovsd %xmm1, 8(%rcx)
vaddsd 8(%rax,%rdi,8), %xmm1, %xmm1
vmovsd %xmm1, 8(%rax,%rdi,8)
vaddsd 16(%r15), %xmm0, %xmm0
vmovsd %xmm0, 16(%rcx)
vaddsd 16(%rax,%rdi,8), %xmm0, %xmm0
vmovsd %xmm0, 16(%rax,%rdi,8)
addq %r13, %rbp
decq %rdx
testq %rdx, %rdx
jg .LBB5_7
leaq -1(%r14), %rdx
incq %r13
cmpq $1, %r14
movq %rdx, %r14
jg .LBB5_6
jmp .LBB5_9
.LBB5_10:
vxorps %xmm0, %xmm0, %xmm0
vmovups %xmm0, (%r15)
movq $0, 16(%r15)
movabsq $numba_gil_ensure, %rax
leaq 36(%rsp), %rcx
callq *%rax
movabsq $PyErr_Clear, %rax
callq *%rax
movabsq $.const.pickledata.2691858029760, %rcx
movabsq $.const.pickledata.2691858029760.sha1, %r8
movabsq $numba_unpickle, %rax
movl $180, %edx
callq *%rax
testq %rax, %rax
je .LBB5_11
movabsq $numba_do_raise, %rdx
movq %rax, %rcx
callq *%rdx
.LBB5_11:
movabsq $numba_gil_release, %rax
leaq 36(%rsp), %rcx
callq *%rax
.LBB5_12:
vmovaps 144(%rsp), %xmm6
addq $168, %rsp
popq %rbx
popq %rbp
popq %rdi
popq %rsi
popq %r12
popq %r13
popq %r14
popq %r15
retq
.Lfunc_end5:
与第二部分相比,第一版的代码很庞大。总体而言,我们可以看到最重要的计算部分大致相同:
----- WITHOUT VIEWS -----
.LBB6_6:
imulq %r8, %r12
vcvtsi2sd %r12, %xmm2, %xmm0
vsqrtsd %xmm0, %xmm0, %xmm0
movq 120(%rsp), %rcx
vmovups %xmm6, (%rcx)
movq $0, 16(%rcx)
movq 248(%rsp), %rdx
vmovsd %xmm0, (%rdx)
vaddsd (%rbp), %xmm0, %xmm1
vmovsd %xmm1, (%rbp)
vaddsd 8(%rcx), %xmm0, %xmm1
vmovsd %xmm1, 8(%rdx)
vaddsd 8(%rbp), %xmm1, %xmm1
vmovsd %xmm1, 8(%rbp)
vaddsd 16(%rcx), %xmm0, %xmm0
vmovsd %xmm0, 16(%rdx)
movq %rax, %r12
vaddsd 16(%rbp), %xmm0, %xmm0
vmovsd %xmm0, 16(%rbp)
cmpb $0, 39(%rsp)
jne .LBB6_7
----- WITH VIEWS -----
.LBB5_7:
vcvtsi2sd %rbp, %xmm2, %xmm0
vsqrtsd %xmm0, %xmm0, %xmm0
vmovups %xmm6, (%r15)
movq $0, 16(%r15)
vmovsd %xmm0, (%rcx)
vaddsd (%rax,%rdi,8), %xmm0, %xmm1
vmovsd %xmm1, (%rax,%rdi,8)
vaddsd 8(%r15), %xmm0, %xmm1
vmovsd %xmm1, 8(%rcx)
vaddsd 8(%rax,%rdi,8), %xmm1, %xmm1
vmovsd %xmm1, 8(%rax,%rdi,8)
vaddsd 16(%r15), %xmm0, %xmm0
vmovsd %xmm0, 16(%rcx)
vaddsd 16(%rax,%rdi,8), %xmm0, %xmm0
vmovsd %xmm0, 16(%rax,%rdi,8)
addq %r13, %rbp
decq %rdx
testq %rdx, %rdx
jg .LBB5_7
虽然第一个版本的代码效率比第二个版本略低,但两者之间的差异绝不足以解释时间巨大差距(约65毫秒与小于0.6毫秒)。
我们还可以看到两个版本中汇编代码中的函数调用是不同的:
----- WITHOUT VIEWS -----
memcpy
NRT_Allocate
NRT_Free
NRT_decref
NRT_incref
NRT_MemInfo_alloc_safe_aligned
----- WITH VIEWS -----
numba_do_raise
numba_gil_ensure
numba_gil_release
numba_unpickle
PyErr_Clear
NRT_decref
NRT_MemInfo_alloc_safe_aligned
NRT_Allocate
、NRT_Free
、NRT_decref
和NRT_incref
函数调用表示编译的代码在热循环中创建了一个新的Python对象,这非常低效。与此同时,第二个版本不执行任何NRT_incref
,我怀疑NRT_decref
实际上从未被调用过(或者可能只被调用了一次)。第二个代码不执行任何Numpy数组分配。看起来对PyErr_Clear
、numba_do_raise
和numba_unpickle
的调用是为了管理可能会引发异常的情况(但令人惊讶的是第一个版本并没有这样做,因此很可能与使用视图有关)。最后,在第一个版本中调用memcpy
表明新创建的数组肯定被复制到了x
中。分配和复制使第一个版本非常低效。
我很惊讶Numba不会为zeros(3)
生成分配。这很好,但您应该尽量避免像这样在热循环中创建数组,因为不能保证Numba始终会优化这样的调用。实际上,它经常不会。
您可以使用基本循环来复制切片的所有项目,以避免任何分配。如果在编译时知道切片的大小,则通常更快。切片复制可能会更快,因为编译器可能更好地向量化代码,但实际上,这些循环相对较好地自动向量化。
可以注意到两个版本的代码中都有vsqrtsd
指令,因此lambda实际上是内联的。
当您将lambda移动到函数之外并将其内容放入另一个jitted函数中时,LLVM可能不会内联该函数。您可以在生成中间表示(IR代码)之前手动请求Numba内联函数,以便LLVM应该生成类似的代码。这可以使用inline="always"
标志完成。尽管这倾向于增加编译时间(因为代码几乎被复制粘贴到调用函数中),但内联对于应用许多进一步的优化(常量传播、SIMD向量化等)至关重要,这可能会带来巨大的性能提升。