【发布时间】:2021-07-18 15:03:50
【问题描述】:
我想在 C# 中使用AVX-512 指令,但我的理解是:不支持它(或者我在互联网上搜索非常糟糕)。所以我决定为它创建自己的绑定。但是我得到了:
外部组件抛出异常。
我不知道我在这里搞砸了什么。
这是我的C 代码:
#include <immintrin.h>
__declspec(dllexport)
__m512i
load_s32(const void *ptr) {
return _mm512_load_epi32(ptr);
}
使用以下命令编译:
gcc -c decl.c -mavx512f
gcc -shared -o libavx512.dll decl.o -Wl,--out-implib,libavx512.dll.a -mavx512f
在C# 我创建了一个包含以下部分的库:
using System.Runtime.InteropServices;
using S64 = System.Int64;
namespace AVX512Sharp
{
[StructLayout(LayoutKind.Sequential, Size = 64)]
public struct M512S32
{
public S64 M0;
public S64 M1;
public S64 M2;
public S64 M3;
public S64 M4;
public S64 M5;
public S64 M6;
public S64 M7;
}
public static class AVX512
{
[DllImport("libavx512.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "load_s32")]
public extern unsafe static M512S32 LoadS32(void* ptr);
}
}
在我的测试程序中,我是这样使用它的:
int* mem = stackalloc int[16];
for (int i = 0; i < 16; ++i)
mem[i] = i * 10;
M512S32 zmm0;
zmm0 = AVX512.LoadS32(mem);
我真的不知道我在这里做错了什么。
注意事项
- 为了测试绑定是否有效,我删除了 SIMD 函数:
__declspec(dllexport)
void
load_s32(const void *ptr) {
return;
}
并且还更新了AVX512 类:
public static class AVX512
{
[DllImport("libavx512.dll", EntryPoint = "load_s32")]
public extern unsafe static void LoadS32(void* ptr);
}
这没有引发异常。
- 在第二步中,我尝试在
C应用程序中使用dll。也没有任何错误。 - 还尝试使用额外的属性,例如:
-Wl,--export-all-symbols、-Wl,--enable-auto-import。相关文档为here。
【问题讨论】:
-
您调试的第一步应该是从非托管 DLL 中删除特定于 AVX 的部分,以确保您已正确设置互操作内容。如果这可行,那么在非托管上下文中使用您的非托管 DLL 以确保它从根本上是正确的。如果在这之后,它仍然不起作用,那么你知道你有一个实际的 C# 问题。
-
@jdweng 这不是必需的,但是我尝试过它并没有用(也是“默认”
struct不能为空)。 stackoverflow.com/questions/7767669/… -
我建议针对 x64 构建库和应用程序(不是任何 CPU),并使用 Fastcall 调用约定。 Cdecl 是 x86 约定,不适用于 x64。 Some read.
-
@jdweng:更正,
_mm512_load_epi32必须是 64 byte 对齐而不是 64 位;这是_mm512_load_si512的一个愚蠢的替代名称,我建议不要使用它。 (What is the difference between _mm512_load_epi32 and _mm512_load_si512?)。仅在进行屏蔽加载时才使用 _epi32 版本,因为这样元素大小才有意义。使用loadu而不是load进行未对齐的加载,但请注意对齐对于 512 位向量的性能更重要:每个未对齐的向量都是缓存行拆分,并且它的减速更大. -
@PeterCordes 是的,我的 MACHINE 上的 CPU 不支持 AVX512。在多台机器上工作有它的缺点。