0

我正在学习如何在 C# 中使用 C++ DLL,并制作了一个 c++ 函数,该函数将两个分配的(编组)变量集相乘。在我将分配的组合大小从 512MB 增加到 1024 之前,一切都在 C# 和 C++ 中运行良好。然后 Visual C# 给出“受保护的内存访问冲突”的错误。其来源是 dll 函数,它用浮点数填充缓冲区。限制必须介于 512MB 和 1024MB 之间。Marshal.alloc 仅接受 int 大小的缓冲区长度,因此每个分配实际上有 2GB 限制,但是当我尝试使用更小的块来超过限制时,会给出相同的错误。

问题:是否有任何在 C# 中没有上限/限制的 directbytebuffer 等效项?还是我在做一些简单的指针错误?

dll 和 main 项目都是针对 64 位的,可以使用普通数组超过 5-6 GB 的内存。

这是写入缓冲区的 c++ 函数:

__declspec(dllexport) void floatOne(long av, int n)
    {
        float * vektor1=(float *)av; 
        _mm256_zeroall();
        __m256 r0=_mm256_setr_ps(1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f,1.0f);

        for(int i=0;i<n;i+=8)
        {

            _mm256_store_ps(vektor1+i, r0); 

        }
        _mm256_zeroall();
        return;
    }

以下是它在 C# 中的使用方式:

public void one()
        {
            floatOne(bufferAdr.ToInt64() + offset, N);
            // offset here is the properly aligned address to start usage
            // N is private variable of vektor class (vector length) 
        }

以下是分配方式:

 public vektor(int n /* number of elements*/, int a /* alignmentı*/)
        {
            N = n;
            bufferAdr = Marshal.AllocHGlobal(4*n + 4*a);
            //a-1 was enough but I put a*4 to be sure it doesnt overflow.
            offset = (a - bufferAdr.ToInt64() % a);
        }

这是DLL导入:

[DllImport("cpuKullanim.dll", EntryPoint = "floatOne")]
        public static extern void floatOne(long adres1, int n);

测试了任何硬件错误的 RAM,但通过了内存测试,因此肯定存在软件问题。

谢谢。

windows7-64位,cpu 64位,两个项目的目标机64位。

4

1 回答 1

3
  __declspec(dllexport) void floatOne(long av, int n)

这是您的代码中的一个严重错误,使用 MSVC 编译时,long类型在 64 位模式下是 32 位。这不足以存储指针。在您开始分配更大的内存块之前,它会意外工作。“av”的正确参数类型至少是指针类型void*。当然,没有理由避免仅仅声明它float*。如果你不试图欺骗编译器,代码总是能更好地工作。您必须在 C# 代码中将其声明为 IntPtr。

您尝试对对齐进行的操作非常难以理解。要求是地址与 SSE2 代码的 16 的倍数对齐。您可以使用此辅助方法:

    static IntPtr AlignAddressForSSE2(IntPtr addr) {
        return new IntPtr((addr.ToInt64() + 15) & unchecked((long)0xfffffffffffffff0L));
    }

还要将 15 添加到 Marshal.AllocHGlobal() 参数(实际上 8 就足够了)。或者简单地从您的 DLL 中导出两个函数,通过使用 _aligned_malloc() 和 _aligned_free() 来处理这个问题。

于 2013-07-21T00:35:21.780 回答