Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/301.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C#中获取AVX512?_C#_Simd_Avx_Avx512 - Fatal编程技术网

如何在C#中获取AVX512?

如何在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

我想用C#中的
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
    。相关文件为
我决定为它创建自己的绑定

你不能。最好的事情,你可以做,而写一个DLL在C或C++使用AVX512,并消耗DLL从C。如果您试图从DLL中导出单个指令,性能将不好,因为内存访问和pinvoke开销。相反,您应该用C编写更大的功能

我真的不知道我做错了什么

您的C函数期望输入指针位于
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
to
ymm15
),当它们在内存中时,尽可能按32字节对齐,运行时不支持AVX512,将您的<代码> M512S32 < /C>作为一种常规结构类型,而不是作为一个本地向量。@如果您不想等待,请在C++中实现您的性能关键函数并使用DLIMPORT。不要导出单个指令,而是导出更大的函数,这些函数将数据从内存流式传输到内存