C方法相当于Java';s DirectByteBuffer 我学习了如何在C++中使用C++ DLL,并生成了一个C++函数,它将两个分配的(集合的)变量集相乘。在C和C++中,所有的工作都很好,直到我把分配的组合大小从512MB增加到1024。然后VisualC#给出了“受保护内存访问冲突”的错误。这一错误的来源是dll函数,该函数用浮点数填充缓冲区。限制必须介于512MB和1024MB之间。alloc只接受int大小的缓冲区长度,因此每个分配实际上有2GB的限制,但当我尝试使用较小的块来超过限制时,会出现相同的错误

C方法相当于Java';s DirectByteBuffer 我学习了如何在C++中使用C++ DLL,并生成了一个C++函数,它将两个分配的(集合的)变量集相乘。在C和C++中,所有的工作都很好,直到我把分配的组合大小从512MB增加到1024。然后VisualC#给出了“受保护内存访问冲突”的错误。这一错误的来源是dll函数,该函数用浮点数填充缓冲区。限制必须介于512MB和1024MB之间。alloc只接受int大小的缓冲区长度,因此每个分配实际上有2GB的限制,但当我尝试使用较小的块来超过限制时,会出现相同的错误,c#,c++,marshalling,bytebuffer,C#,C++,Marshalling,Bytebuffer,问题:是否有任何directbytebuffer等价物在C#中没有上限/限制? 还是我在做一些简单的指针错误 dll和main项目都是64位目标,对于普通阵列可以使用超过5-6 GB的内存 这里是写入缓冲区的C++函数: __declspec(dllexport) void floatOne(long av, int n) { float * vektor1=(float *)av; _mm256_zeroall(); __m256 r0

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

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;
    }
以下是分配方式:

 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,但通过了mem测试,因此一定存在软件问题

谢谢

Windows 7-64位,cpu 64位,两个项目的目标计算机64位

  __declspec(dllexport) void floatOne(long av, int n)
这是代码中的一个严重错误,当使用MSVC编译时,长类型在64位模式下为32位。它不够大,无法存储指针。在您开始分配更大的内存块之前,它将意外地工作。“av”的正确参数类型是指针类型,至少
void*
。当然,没有理由不直接声明它
float*
。如果你不想愚弄编译器,代码总是工作得更好。您必须在C代码中将其声明为IntPtr

您试图对对齐所做的操作是相当难以理解的。对于SSE2代码,要求地址与16的倍数对齐。您可以使用以下帮助器方法:

    static IntPtr AlignAddressForSSE2(IntPtr addr) {
        return new IntPtr((addr.ToInt64() + 15) & unchecked((long)0xfffffffffffffff0L));
    }
还要在Marshal.AllocHGlobal()参数中添加15(实际上8就足够了)。或者只需使用_aligned_malloc()和_aligned_free()从DLL中导出两个函数即可解决此问题

这是代码中的一个严重错误,当使用MSVC编译时,长类型在64位模式下为32位。它不够大,无法存储指针。在您开始分配更大的内存块之前,它将意外地工作。“av”的正确参数类型是指针类型,至少
void*
。当然,没有理由不直接声明它
float*
。如果你不想愚弄编译器,代码总是工作得更好。您必须在C代码中将其声明为IntPtr

您试图对对齐所做的操作是相当难以理解的。对于SSE2代码,要求地址与16的倍数对齐。您可以使用以下帮助器方法:

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

还要在Marshal.AllocHGlobal()参数中添加15(实际上8就足够了)。或者只需使用_aligned_malloc()和_aligned_free()从DLL中导出两个函数即可解决此问题。

那么,为什么要使用
Marshal.AllocHGlobal
?我不确定你为什么要这么做,你能详细说明你到底想做些什么吗?结果应该是什么等@aevitas分配空间作为点积函数和矩阵乘法的大缓冲区。这比并行更快。对于在普通数组上缩减的版本(速度是并行的6-7倍),它在java上运行得非常好,但我试图在C#中实现同样的效果。您是否得到了一个
OutOfMemoryException
?否,内存访问冲突错误。从使用内部写内存的C++函数中,我看像<代码>偏移量=(a -pBuffr.toItn64()%a);<代码>的计算结果为负值或其他值,导致您的
AccessViolationException
。调试时在其上放置一个断点,并查看该等式的实际结果。如果分配不足,则会出现不同的异常。那么,为什么要为此使用
Marshal.AllocHGlobal
?我不确定你为什么要这么做,你能详细说明你到底想做些什么吗?结果应该是什么等@aevitas分配空间作为点积函数和矩阵乘法的大缓冲区。这比并行更快。对于在普通数组上缩减的版本(速度是并行的6-7倍),它在java上运行得非常好,但我试图在C#中实现同样的效果。您是否得到了一个
OutOfMemoryException
?否,内存访问冲突错误。从使用内部写内存的C++函数中,我看像<代码>偏移量=(a -pBuffr.toItn64()%a);<代码>的计算结果为负值或其他值,导致您的
AccessViolationException
。调试时在其上放置一个断点,并查看该等式的实际结果。如果您分配不足,您将得到一个不同的异常。非常感谢,这解决了我的错误。在DLL中使用(void*),在C#中使用IntPtr。我还尝试了malloc/free包装器来查看它是如何工作的,但是由于某些原因malloc没有分配(或者它没有显示在windows管理器中),但是工作很好,free也很好,没有任何警告。非常感谢,这解决了我的错误。在DLL中使用(void*),在C#中使用IntPtr。我还尝试了malloc/free包装器来查看它是如何工作的,但是由于某种原因malloc没有分配(或者它没有显示在windows管理器中),但是工作正常,free工作正常,没有任何警告。