如何在C#中获取AVX512?
我想用C#中的如何在C#中获取AVX512?,c#,simd,avx,avx512,C#,Simd,Avx,Avx512,我想用C#中的AVX-512指令,但我的理解是:没有对它的支持(或者我在互联网上搜索的能力非常差)。所以我决定为它创建自己的绑定。然而,我得到: 外部组件引发了异常 我不知道我把这里搞砸了 这是我的C代码: #包括 __declspec(dllexport) __m512i 荷载s32(const void*ptr){ 返回mm512加载epi32(ptr); } 它是使用以下命令编译的: gcc -c decl.c -mavx512f gcc -shared -o libavx512.dll
AVX-512
指令,但我的理解是:没有对它的支持(或者我在互联网上搜索的能力非常差)。所以我决定为它创建自己的绑定。然而,我得到:
外部组件引发了异常
我不知道我把这里搞砸了
这是我的C
代码:
#包括
__declspec(dllexport)
__m512i
荷载s32(const void*ptr){
返回mm512加载epi32(ptr);
}
它是使用以下命令编译的:
gcc -c decl.c -mavx512f
gcc -shared -o libavx512.dll decl.o -Wl,--out-implib,libavx512.dll.a -mavx512f
在C#
中,我创建了一个库,其中包含以下部分:
使用System.Runtime.InteropServices;
使用S64=System.Int64;
名称空间AVX512Sharp
{
[StructLayout(LayoutKind.Sequential,Size=64)]
公共结构M512S32
{
公共S64 M0;
公共S64 M1;
公共建筑面积64平方米;
公共供水64立方米;
公共S64 M4;
公共S64 M5;
公共S64 M6;
公共S64 M7;
}
公共静态类AVX512
{
[DllImport(“libavx512.dll”,CallingConvention=CallingConvention.Cdecl,EntryPoint=“load_s32”)]
公共外部不安全静态M512S32荷载32(无效*ptr);
}
}
在我的测试程序中,我是这样使用它的:
int*mem=stackalloc int[16];
对于(int i=0;i<16;++i)
mem[i]=i*10;
M512S32-zmm0;
zmm0=AVX512.载荷32(mem);
我真的不知道我做错了什么
笔记
- 要测试绑定工作是否已删除SIMD函数,请执行以下操作:
\u declspec(dllexport)
无效的
荷载s32(const void*ptr){
返回;
}
并且还更新了AVX512
类:
公共静态类AVX512
{
[DllImport(“libavx512.dll”,EntryPoint=“load_s32”)]
公共外部不安全静态无效荷载32(无效*ptr);
}
这没有引发异常
- 在第二步中,我尝试在
应用程序中使用C
。也没有任何错误dll
- 还尝试使用其他属性,例如:
,-Wl,--export all symbol
。相关文件为-Wl,--enable auto import
rcx
寄存器中,并在zmm0
向量寄存器中返回结果
您的C#函数不知道zmm0
。运行时在堆栈上为返回值分配64个字节,在rcx
寄存器中传递返回值缓冲区的地址,在rdx
寄存器中传递输入指针,并期望函数在rax
寄存器中返回在rcx
中传递的指针
interop两侧的语言对调用约定不一致,代码在运行时崩溃。调试的第一步应该是从非托管DLL中删除AVX特定部分,以确保已正确设置interop内容。如果可行,那么在非托管上下文中使用非托管DLL以确保其基本正确。如果在所有这些之后,它仍然不起作用,那么你就知道你有一个实际的C#问题。@jdweng它不是必需的,但是我尝试了它,但它不起作用(还有一个“默认”
struct
不能为空)。我建议基于x64构建库和应用程序(而不是任何CPU),并使用Fastcall调用约定。Cdecl是x86约定,不适用于x64@jdweng:Correction,\u mm512\u load\u epi32
必须是64字节对齐,而不是64位;这是\u mm512\u load\u si512
的一个愚蠢的替代名称,我建议永远不要使用它。(). 只有在进行屏蔽加载时才使用_epi32版本,因为这样元素大小才有意义。对于未对齐的加载,请使用loadu
而不是load
,但请注意,对齐对于512位向量的性能更为重要:每个未对齐的向量都是缓存线分割,速度更慢。@PeterCordes是的,我机器上的CPU不支持AVX512。在多台机器上工作有它的缺点。(而且,querent显然把他们的机器搞混了(?)而且,这也没什么帮助。C函数中的非法指令错误,所以它在返回之前就崩溃了。但是,是的,包装单个指令对于性能来说是不可能的,即使你正确地执行了调用约定。)@Soons我正试图复制MS对AVX2
所做的操作。我使用ILSpy
查看了他们的代码,他们在那里使用了类似的结构。我确实从互操作函数调用中获得了数据(在修复了调用转换之后),但你是对的:这里的性能不会完美(甚至不好)。另外.NET5
引入了“本机函数指针”()。有人能用它们来改善那里的开销吗?@Hrant你在ILSpy中看到的只是故事的高级部分。注意Vector256
结构在CIL中用[固有]
属性标记。NET运行时知道如何正确处理这些类型:将它们保存在这些向量寄存器中(如果是32字节的AVX向量,它们被命名为ymm0
toymm15
),当它们在内存中时,尽可能按32字节对齐,运行时不支持AVX512,将您的<代码> M512S32 < /C>作为一种常规结构类型,而不是作为一个本地向量。@如果您不想等待,请在C++中实现您的性能关键函数并使用DLIMPORT。不要导出单个指令,而是导出更大的函数,这些函数将数据从内存流式传输到内存