我學習瞭如何在C#中使用C++ DLL,並製作了一個C++函數,用於乘以兩個分配的(Marshalled)變量集合。在C#和C++中一切正常,直到我將分配的總大小從512MB增加到1024。然後Visual C#給出「受保護的內存訪問衝突」的錯誤。這是dll函數,它使用浮動填充緩衝區。限制必須介於512MB和1024MB之間。 Marshal.alloc只接受int大小的緩衝區長度,所以每個分配實際上有2GB的限制,但是當我嘗試更小的塊來超過限制時,會給出相同的錯誤。相當於Java的DirectByteBuffer的C#方法
問題:在C#中是否有任何不受限制/限制的直接字節緩衝等價物? 還是我在做一些簡單的指針錯誤?
dll和主要項目都是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,但通過了mem測試,所以必須有軟件問題。
謝謝。
windows7-64位,cpu 64位,目標機器64bit,用於這兩個項目。
那麼爲什麼你完全使用'Marshal.AllocHGlobal'呢?我不確定你爲什麼試圖做這個不安全的事情,你能詳細說明你究竟想要做些什麼嗎?結果應該如何,等等。 – aevitas
@aevitas爲點積函數和矩陣乘法分配空間作爲大緩衝區。這比Parallel.For版本更快,速度比普通數組還要快(速度提高了6-7倍)。它在java上工作得很好,但是我試圖在C#中做同樣的事情。 –
你是否在遇到OutOfMemoryException? – aevitas