2012-04-19 42 views
2

我設置了一個非常大的數組來處理原始神經元模擬。爲陣列分配內存(大約8-9 Gig)時,新[]會出現問題。我能夠獲得C風格的malloc來保留內存,但只要我嘗試分配一個值,就會得到訪問衝突讀取位置0xffffffffffffffff。malloc與巨大的多維數組,失敗的神經科學模擬

我使用Visual Studio 2010 Professional運行64位Windows 7。我試過用嵌套循環的malloc和new [],它們也崩潰了。

如果malloc無法做到這一點,我還應該考慮什麼?我需要一些可以非常快地訪問大內存空間的東西。謝謝您的考慮。

#include "stdafx.h" 
#include <iostream> 
#include <time.h> 
#include <stdlib.h> 
#include <iomanip> 
#include <locale> 
#include <math.h> 
using namespace std; 

int nRows; 
int nCols; 
int nDepth; 
int nData; 

int main() 
{ 
     //unsigned long int brainSize=100; 
     //nRows = int(pow(brainSize,0.3333333333333333333333333333))+1; 
      nRows=80; 
     nCols=nRows; 
     nDepth=nRows; 
     nData=2000; 

     double brainData = nRows*nCols*nDepth*nData; 
     double brainBits = 4*brainData; 
     cout.imbue(std::locale("")); 
     cout << fixed << "Brain size : " << nRows*nCols*nDepth << " neurons \nBrain integers : " << setprecision(0) << brainData << "\nBrain bits: " << brainBits << endl; 

    __int64 ****brain; 
    brain = (__int64 ****)malloc(nRows*nCols*nDepth*nData*sizeof(__int64 ****)); 
     cout << "Brain initialized."; 
     brain [2][2][2][2]=2; // error is here. 
     cout << brain[2][2][2][2]; 


    int breaker; 
    cin >> breaker; //pause 
    return 0; 

} 

回答

2

有幾件事情要考慮:

  • 你確定你正在創建一個64位可執行文件?正在運行
  • 有多少空閒內存可用(這包括物理和交換)
  • 您通過哪種類型的malloc?請確保您使用size_t而不是int
  • 也許VirtualAlloc就可以了(限制你的程序到Windows雖然)

你可能要考慮使用內存映射文件來代替。不是自己分配所有內存,而是分配它,但它由文件支持。操作系統然後擔心確保當您訪問它時(您的操作系統就像是正常的new/malloc的內存),它可供您使用。如果有足夠的物理內存可用,它可能會將整個內存保留在內存中,否則會根據需要將其分頁。

通常情況下,內存映射文件會更好地工作,因爲即使在內存較少的系統上,該文件也應該始終有效。而且它會允許更高的內存使用量。當然,你可能會建立你自己的緩存方案(在內存中留下一些東西,其他東西放在磁盤上),但操作系統設計人員在這些方面非常擅長,因爲這可能不是你的主要目標(構建緩存系統),你也可以讓操作系統完成它的工作。

+0

謝謝你的回覆。我有12G的DDR3內存可用;發佈的數組<95%可用。 。我已經縮小了數組值,佔用不到20%的RAM;崩潰是一樣的。它似乎主要是在第四維(nData)比其他部分大得多時這樣做的。我可能無法使用該磁盤,因爲我會將部分「大腦」劃分爲異步CPU線程或稍後更有可能的GPU內核。我按照你的建議添加了size_t,但收到相同的崩潰?我用下面的代碼替換了這一行:brain =(__int64 ****)malloc(size_t(nRows * nCols * nDepth * nData * sizeof(__ int64 ****))); – ScienceDilletante 2012-04-19 03:28:38

1

問題是,您正在聲明一個指向指向64位整數指針的指針的指針,而不是64位整數的四維數組。當您用[2][2][2][2]的鏈取消引用時,編譯器將在剛剛分配的未初始化塊中查找指針,嘗試對其進行解引用並立即崩潰。

如果您至少四分之三的尺寸(比如,nRowsnColumnsnDepth)都是編譯時間常數,你可以分配nData 3-d陣列,並使用常規的方括號語法來訪問元素。如果這是不可能的,你將不得不忍受指針的開銷,或者分配一個「普通」數組並實現你自己的尋址方案,以使它相信它是4-D。

P.S.我在這裏默默地假設使用vector<...>的開銷在你的情況下是不可接受的。但是,如果你有足夠的內存來存放額外的指針,我肯定會選擇64位整數向量的向量向量:它速度快,可靠,易於使用。

編輯:這是如果三個四個維度的是常數,你可以做什麼:

#include <iostream> 

const int nRows = 11; 
const int nColumns = 13; 
const int nDepth = 17; 

typedef long long brain_block[nRows][nColumns][nDepth]; 

int main() { 
    int nData = 123; 
    brain_block *brain = (brain_block*)malloc(nData*sizeof(brain_block)); 
    memset(brain, 0, nData*sizeof(brain_block)); 
    brain[2][2][2][2] = 2; 
    std::cout << brain[2][2][2][2] << std::endl; 
    free(brain); 
} 
+0

謝謝你的回覆。我必須避免向量<>,因爲我想將每個可能的RAM字節都壓縮到模擬的大腦中 - 大型網絡的需求是巨大的。最簡單的點神經元如果按比例增加到人類新皮層,則需要大約7太字節。所以速度和最低的佔地面積至關重要。您可以詳細說明nData 3-D數組的想法嗎?所有變量保存一個(行/列/深度)可以保持不變。 nData存儲神經元和其他神經元之間的連接數據(每個2000),連接強度(興奮/抑制)和神經元興奮狀態。謝謝! – ScienceDilletante 2012-04-19 03:36:38

+0

@ScienceDilletante我編輯了答案,包括如果行/列/深度是常量該怎麼做的例子。 – dasblinkenlight 2012-04-19 10:14:44

+0

非常感謝 - 這真是一種魅力! – ScienceDilletante 2012-04-24 00:00:40