gpt4 book ai didi

c# - 将 blittable 结构复制到非托管内存位置的最快方法 (IntPtr)

转载 作者:行者123 更新时间:2023-11-30 20:48:25 25 4
gpt4 key购买 nike

我有一个类似于下面的函数:

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void SetVariable<T>(T newValue) where T : struct {
// I know by this point that T is blittable (i.e. only unmanaged value types)

// varPtr is a void*, and is where I want to copy newValue to
*varPtr = newValue; // This won't work, but is basically what I want to do
}

我看到了 Marshal.StructureToIntPtr(),但它似乎很慢,而且这是对性能敏感的代码。如果我知道 T 类型,我可以将 varPtr 声明为 T*,但是...嗯,我不知道。

无论哪种方式,我都在寻求最快的方法来做到这一点。 “安全”不是问题:到代码中的这一点,我知道结构 T 的大小将完全适合 varPtr 指向的内存。

最佳答案

一个答案是在 C# 中重新实现 native memcpy,利用 native memcpy 尝试执行的相同优化技巧。你可以看到微软在他们自己的源代码中这样做。查看Buffer.cs Microsoft 引用源中的文件:

     // This is tricky to get right AND fast, so lets make it useful for the whole Fx.
// E.g. System.Runtime.WindowsRuntime!WindowsRuntimeBufferExtensions.MemCopy uses it.
internal unsafe static void Memcpy(byte* dest, byte* src, int len) {

// This is portable version of memcpy. It mirrors what the hand optimized assembly versions of memcpy typically do.
// Ideally, we would just use the cpblk IL instruction here. Unfortunately, cpblk IL instruction is not as efficient as
// possible yet and so we have this implementation here for now.

switch (len)
{
case 0:
return;
case 1:
*dest = *src;
return;
case 2:
*(short *)dest = *(short *)src;
return;
case 3:
*(short *)dest = *(short *)src;
*(dest + 2) = *(src + 2);
return;
case 4:
*(int *)dest = *(int *)src;
return;
...

有趣的是,他们 native 实现了最大 512 的所有大小的 memcpy;大多数大小都使用指针别名技巧来让 VM 发出对不同大小进行操作的指令。只有在 512,他们才最终开始调用 native memcpy:

        // P/Invoke into the native version for large lengths
if (len >= 512)
{
_Memcpy(dest, src, len);
return;
}

据推测,原生 memcpy 甚至更快,因为它可以手动优化以使用 SSE/MMX 指令执行复制。

关于c# - 将 blittable 结构复制到非托管内存位置的最快方法 (IntPtr),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24619472/

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