Большой 2D массив дает отказ сегментации

Хорошо, я нашел ответ сам: в основном это делается простым изменением import keras на import tensorflow.keras as keras. Tf.keras позволяет передавать набор проверки также как тензор:

X, Y = datasetLoader('PATH-TO-DATASET', 264)
X_val, Y_val = datasetLoader('PATH-TO-VALIDATION-DATASET', 264)

# ... define and compile the model like above

parallel_model.fit(
    epochs= epochs,
    steps_per_epoch= STEPS_PER_EPOCH,
    shuffle= False,
    validation_data= (X_val, Y_val),
    validation_steps= STEPS_PER_VALIDATION_EPOCH
)  
23
задан unwind 12 May 2009 в 06:58
поделиться

7 ответов

Если ваша программа выглядит так ...

int main(int, char **) {
   double x[5000][500],y[5000][500],z[5000][500];
   // ...
   return 0;
}

... значит, вы переполняете стек. Самый быстрый способ исправить это - добавить слово static .

int main(int, char **) {
   static double x[5000][500],y[5000][500],z[5000][500];
   // ...
   return 0;
}

Второй самый быстрый способ исправить это - переместить объявление из функции:

double x[5000][500],y[5000][500],z[5000][500];
int main(int, char **) {
   // ...
   return 0;
}

Третий самый быстрый способ исправить это - для выделения памяти в куче:

int main(int, char **) {
   double **x = new double*[5000];
   double **y = new double*[5000];
   double **z = new double*[5000];
   for (size_t i = 0; i < 5000; i++) {
      x[i] = new double[500];
      y[i] = new double[500];
      z[i] = new double[500];
   }
   // ...
   for (size_t i = 5000; i > 0; ) {
      delete[] z[--i];
      delete[] y[i];
      delete[] x[i];
   }
   delete[] z;
   delete[] y;
   delete[] x;

   return 0;
}

Четвертый самый быстрый способ - выделить память в куче с помощью std :: vector. В вашем файле меньше строк, но больше строк в модуле компиляции, и вы должны либо придумать значимое имя для производных векторных типов, либо поместить их в анонимное пространство имен, чтобы они не загрязняли глобальное пространство имен:

#include <vector>
using std::vector
namespace { 
  struct Y : public vector<double> { Y() : vector<double>(500) {} };
  struct XY : public vector<Y> { XY() : vector<Y>(5000) {} } ;
}
int main(int, char **) {
  XY x, y, z;
  // ...
  return 0;
}

Пятый самый быстрый способ - разместить их в куче, но использовать шаблоны, чтобы размеры не были настолько удалены от объектов:

include <vector>
using namespace std;
namespace {
  template <size_t N>
  struct Y : public vector<double> { Y() : vector<double>(N) {} };
  template <size_t N1, size_t N2>
  struct XY : public vector< Y<N2> > { XY() : vector< Y<N2> > (N1) {} } ;
}
int main(int, char **) {
  XY<5000,500> x, y, z;
  XY<500,50> mini_x, mini_y, mini_z;
  // ...
  return 0;
}

Самый эффективный способ - выделить двумерные массивы как одномерные, а затем использовать арифметику индексов.

Все вышеизложенное предполагает, что у вас есть какая-то причина, хорошая или плохая, для желания создать свой собственный механизм многомерного массива. Если у вас нет причин и вы планируете снова использовать многомерные массивы, настоятельно рекомендуем установить библиотеку:

64
ответ дан 29 November 2019 в 00:41
поделиться

Ваше объявление должно появиться на верхнем уровне, вне какой-либо процедуры или метода.

Безусловно самый простой способ диагностировать segfault в коде C или C ++ - это используйте valgrind . Если один из ваших массивов неисправен, valgrind точно определит, где и как. Если ошибка в другом месте, он также сообщит вам об этом.

valgrind можно использовать с любым двоичным файлом x86, но он предоставит дополнительную информацию, если вы скомпилируете с помощью gcc -g .

3
ответ дан 29 November 2019 в 00:41
поделиться

Эти массивы находятся в стеке. Стеки довольно ограничены по размеру. Вы наверняка столкнетесь с ...

16
ответ дан 29 November 2019 в 00:41
поделиться

. Вы можете попробовать и использовать Boost.Multi_array

typedef boost::multi_array<double, 2> Double2d;
Double2d x(boost::extents[5000][500]);
Double2d y(boost::extents[5000][500]);
Double2d z(boost::extents[5000][500]);

Фактически большой фрагмент памяти будет выделен в куче и автоматически освобожден при необходимости.

5
ответ дан 29 November 2019 в 00:41
поделиться

По-моему, у вас есть переполнение стека, честно говоря, Спольски!

Попробуйте скомпилировать свою программу с параметром gcc -fstack-check. Если ваши массивы слишком велики для размещения в стеке, вы получите исключение StorageError.

Я думаю, что это хорошая ставка, поскольку 5000 * 500 * 3 удвоений (по 8 байтов каждый) составляют около 60 мегабайт - ни одна платформа не имеет для этого достаточного стека. Вам нужно будет разместить свои большие массивы в куче.

1
ответ дан 29 November 2019 в 00:41
поделиться

Другим решением предыдущих было бы выполнение

ulimit -s stack_area

для расширения максимального стека.

0
ответ дан 29 November 2019 в 00:41
поделиться

Одно замечание насчет постоянного использования вектора: насколько я понимаю, если вы отойдете от конца массива, он просто выделит более крупный массив и скопирует все, что может создать незаметные и трудно обнаруживаемые ошибки, когда вы действительно привязаны к работе с массивом фиксированного размера. По крайней мере, с реальным массивом вы столкнетесь с ошибкой, если дойдете до конца, что упростит обнаружение ошибки.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {

typedef double (*array5k_t)[5000];

array5k_t array5k = calloc(5000, sizeof(double)*5000);

// should generate segfault error
array5k[5000][5001] = 10;

return 0;
}
2
ответ дан 29 November 2019 в 00:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: