Как правильно сделать член класса большим массивом 2D C?

#c #arrays #class

#c #массивы #класс

Вопрос:

У меня есть очень простой фрагмент кода:

 #include <iostream>
#include <random>

using namespace std;

const int K=1;
const int N=1024*K;
const int M=1024;

class C {
  public:
  C(){
    minstd_rand0 g(1);
    for(int i=0; i<N;   i) for(int j=0; j<M;   j)
        a[i][j]=generate_canonical<float, numeric_limits<float>::digits>(g);
     }
  private:
  float a[N][M];
};

int main()
{
  C c;
  cout<<"size="<<N*M/(1<<20)<<endl;
  return 0;
}
 

При K = 1 код работает, но при K = 2 происходит немедленный сбой из-за ошибки сегментации.
Итак, как я понимаю, существует некоторое ограничение на объем данных, который может содержать произвольный класс (не более этого объема МБ). Как точно узнать эту сумму?

В своей работе я имею дело с массивами, подобными a, которые обозначают распределение функции вероятности на некотором отрезке линии. У меня есть десятки таких массивов. Я предполагал поместить все эти массивы в 1 класс менеджера, который будет обрабатывать их все, но, как показывает этот пример, это невозможно, возникает ошибка сегментации. Итак, у меня есть, например, 10 массивов (я хотел бы инкапсулировать их все внутри какого-то одного объекта) типа double с количеством элементов 2x1024x1024. Как правильно управлять ими в программе?

P. S. Если распределить их по куче:

 class C {
  public:
  C(){
    p = new float*[N];
    for(int i=0; i<N;   i) p[i]=new float[M];
    minstd_rand0 g(1);
    for(int i=0; i<N;   i) for(int j=0; j<M;   j)
        p[i][j]=generate_canonical<float, 
                numeric_limits<float>::digits>(g);
  }
  ~C(){
    for(int i=0; i<N;   i) delete [] p[i];
    delete [] p;
  }
  private:
  float ** p;
};
 

программа работает даже при K=100. Правильно ли это управлять ими?
В конце концов, есть ли способ выделить массив статически, не делая его статическим членом класса?

P. P. S. Этот фрагмент кода работает:

 const int K=10;
const int N=1024*K;
const int M=1024;
float a[N][M];

class C {
  public:
  C(){
    p=(float *)a;
    minstd_rand0 g(1);
    for(int i=0; i<N;   i) for(int j=0; j<M;   j)
      p[i*M j]=generate_canonical<float, 
               numeric_limits<float>::digits> 
               (g);
    }
  public:
  float *p;
};
 

Но я не знаю, правильно ли это обрабатывать такие большие массивы.

Комментарии:

1. При работе с чрезвычайно большими данными вам захочется распределить их кучно. Автоматическое хранилище на самом деле не предназначено для использования для данных такого масштаба, что объясняет проблему, с которой вы столкнулись. Нет конкретного жесткого ограничения на то, сколько автоматической памяти вам предоставляется (это будет зависеть от операционной системы и, возможно, архитектуры вашего процессора), но это не означает, что оно должно быть доведено до предела.

2. Для современной ОС на настольном компьютере ожидайте от 1 до 10 МБ автоматического хранилища. Для встроенной системы все ставки отменяются.

3. Поскольку ваш класс «manager» по своей природе является единственным, вы можете использовать static float a[N][M]; , и проблема исчезнет. Быстрее и проще, чем куча. static объем памяти исчисляется в гигабайтах, предполагая K , что <= ~200 вы не запустите его.

4. Спасибо за ответ. Я не могу использовать статические члены класса. Я использую OpenACC для компиляции кода для его запуска на GPU. OpenACC не позволяет использовать статические члены класса.