如何解决C# 中是否有限制等效项 注意
我有以下函数(我对其进行了一些清理以使其更容易理解),它采用目标数组获取索引 n
处的元素将 src1[i]
添加到其中,然后将其相乘与 src2[i]
(没什么特别的):
static void F(long[] dst,long[] src1,long[] src2,ulong n)
{
dst[n] += src1[n];
dst[n] *= src2[n];
}
不,这会生成以下 ASM
:
<Program>$.<<Main>$>g__F|0_0(Int64[],Int64[],UInt64)
L0000: sub rsp,0x28
L0004: test r9,r9
L0007: jl short L0051
L0009: mov rax,r9
L000c: mov r9d,[rcx+8]
L0010: movsxd r9,r9d
L0013: cmp rax,r9
L0016: jae short L0057
L0018: lea rcx,[rcx+rax*8+0x10]
L001d: mov r9,rcx
L0020: mov r10,[r9]
L0023: mov r11d,[rdx+8]
L0027: movsxd r11,r11d
L002a: cmp rax,r11
L002d: jae short L0057
L002f: add r10,[rdx+rax*8+0x10]
L0034: mov [r9],r10
L0037: mov edx,[r8+8]
L003b: movsxd rdx,edx
L003e: cmp rax,rdx
L0041: jae short L0057
L0043: imul r10,[r8+rax*8+0x10]
L0049: mov [rcx],r10
L004c: add rsp,0x28
L0050: ret
L0051: call 0x00007ffc9dadb710
L0056: int3
L0057: call 0x00007ffc9dadbc70
L005c: int3
因为你可以添加一堆东西,因为我可以保证 n
将在合法范围之间:我可以使用指针。
static unsafe void G(long* dst,long* src1,long* src2,ulong n)
{
dst[n] += src1[n];
dst[n] *= src2[n];
}
现在生成更简单的ASM
:
<Program>$.<<Main>$>g__G|0_1(Int64*,Int64*,UInt64)
L0000: lea rax,[rcx+r9*8]
L0004: mov rcx,rax
L0007: mov rdx,[rdx+r9*8]
L000b: add [rcx],rdx
L000e: mov rdx,[rax] ; loads the value again?
L0011: imul rdx,[r8+r9*8]
L0016: mov [rax],rdx
L0019: ret
您可能已经注意到,那里有一个额外的 MOV
(我想,至少我想不通它为什么在那里)。
问题
注意
void
f(int64_t *dst,int64_t *src1,int64_t *src2,uint64_t n) {
dst[n] += src1[n];
dst[n] *= src2[n];
}
void
g(int64_t *restrict dst,int64_t *restrict src1,int64_t *restrict src2,uint64_t n) {
dst[n] += src1[n];
dst[n] *= src2[n];
}
这会产生:
f:
mov r10,rdx
lea rdx,[rcx+r9*8]
mov rax,QWORD PTR [rdx]
add rax,QWORD PTR [r10+r9*8]
mov QWORD PTR [rdx],rax ; this is strange. It loads the value back to [RDX]?
; shouldn't that be other way around? I don't kNow.
imul rax,QWORD PTR [r8+r9*8]
mov QWORD PTR [rdx],rax
ret
g:
mov r10,QWORD PTR [r10+r9*8]
imul rax,rax
ret
解决方法
这个:
dst[n] = (dst[n] + src1[n]) * src2[n];
删除额外的 mov
。
在 C#
中,没有与 restrict
语言中的 C
限定符等效。
在C#
ECMA-334:2017 语言规范的23. Unsafe Code
章中,没有语法指定必须只能通过特定指针访问部分内存。并且没有语法指定指针指向的内存区域不重叠。因此不存在这样的等价物。这可能是因为 C# 是一种托管语言,unsafe
语法允许使用指针/非托管内存是 C# 中的一个边缘情况。指针上的 restrict
将是边缘情况的边缘情况。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。