2

プリミティブ ニューロンのシミュレーションを処理するために非常に大きな配列を設定しています。New[] は、配列にメモリ (約 8 ~ 9 ギガ) を割り当てるときに失敗します。C スタイルの malloc を取得してメモリを予約することはできましたが、値を割り当てようとするとすぐに、場所 0xffffffffffffffff を読み取るアクセス違反が発生します。

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;

}
4

2 に答える 2

2

考慮すべき点がいくつかあります。

  • 64 ビットの実行可能ファイルを作成していますか? ただ走っているだけ
  • 利用可能な空きメモリの量 (これには、物理​​メモリとスワップの両方が含まれます)
  • あなたはどのタイプに渡しmallocますか?size_t使用していないことを確認してくださいint
  • たぶんVirtualAllocうまくいくでしょう(ただし、プログラムはWindowsに制限されます)

代わりに、メモリ マップト ファイルの使用を検討することをお勧めします。すべてのメモリを自分で割り当てるのではなく、割り当てますが、ファイルによってサポートされます。new次に、オペレーティングシステムは、アクセスするときに(通常の/ malloc'dメモリであるかのように)アクセスできることを確認することを心配します. 利用可能な物理 RAM が十分にある場合は、すべてをメモリに保持する可能性があります。それ以外の場合は、必要に応じてビットをページインします。

一般に、メモリ マップされたファイルは、メモリが少ないシステムでも常に機能するため、より適切に機能します。また、はるかに高いメモリ使用量が可能になります。確かに、おそらく独自のキャッシング スキームを構築することもできます (一部をメモリに保持し、他のものをディスクに保持する)。ただし、オペレーティング システムの設計者はこれらのことをかなり得意としています。 OSにその仕事をさせたほうがいいでしょう。

于 2012-04-19T02:28:16.330 に答える
1

問題は、64ビット整数の4次元配列ではなく、64ビット整数へのポインターへのポインターへのポインターへのポインターを宣言していることです。のチェーンを使用して逆参照すると[2][2][2][2]、コンパイラは、割り当てたばかりの初期化されていないブロックでポインタを検索し、逆参照を試みて、すぐにクラッシュします。

nRows4つのサイズ(たとえば、、、、nColumnsおよび)のうち少なくとも3つnDepthがコンパイル時定数である場合はnData、3D配列を割り当て、通常の角括弧構文を使用して要素にアクセスできます。それが不可能な場合は、ポインタのオーバーヘッドに耐えるか、「プレーン」配列を割り当てて独自のアドレス指定スキームを実装し、4-Dであると信じ込ませる必要があります。

PS私はここで、vector<...>あなたの状況では使用のオーバーヘッドが法外なものであると黙って仮定しています。ただし、追加のポインタ用に十分なメモリがある場合は、64ビット整数のベクトルのベクトルのベクトルを使用します。高速で信頼性が高く、使いやすいです。

編集:これは、4つの次元のうち3つが定数である場合に実行できることです。

#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);
}
于 2012-04-19T02:38:12.913 に答える