2015-07-02 3 views
0

Я создал разреженную матрицу mat в C++, используя пакет Eigen. Матрица работает отлично, но я пытаюсь преобразовать ее в массив для использования в качестве растрового изображения. Размер mat равен N + 1.Преобразование Eigen разреженной матрицы в массив в C++ с использованием

наивности, я пытался делать следующее:

double zmat[N+1][N+1]; 

    for(int i=0; i<=N; i++){ 
     for(int j=0; j<=N; j++){ 
      zmat[i][j]=mat.coeffRef(i,j); 
      } 
    } 

Но это дает мне исключение, когда я отладки:

Необработанное исключение при 0x0116B2C7 в Open_GL_test.exe: 0xC00000FD: переполнение стека (параметры : 0x00000000, 0x001D2000).

Любые мысли?

+0

Какова ценность 'N'? Он должен быть большим, вы попадаете в переполнение стека. – CoryKramer

+0

Почему вы используете эту нотацию N + 1? IMHO 'zmat [N] [N]' и 'i user463035818

+0

@CoryKramer N = 600 в этом примере. –

ответ

3
double zmat[N+1][N+1]; 

Это то, что вызывает у вас проблемы. Объявление большой матрицы как локальной переменной в функции не является хорошей идеей. Локальные переменные выделяются в стеке. Многие машины ограничивают размер стека небольшим количеством данных. На моей машине ограничение стека составляет около 8 мегабайт. Это означает, что значение N, превышающее примерно тысячу, сразу же приведет к переполнению стека. Значение N, превышающее несколько сотен (но меньше тысячи), приведет к переполнению стека с жесткой трассировкой где-то дальше по дереву вызовов.

Не выделяйте большие объемы данных в стек. Некоторые альтернативы для

  • Объявляем переменную в области видимости пространства имен,
  • Выделяют (а потом бесплатно) матрицу с помощью new и delete,
  • Используйте обычный матричный Эйген, который делает new и delete для вас ,
1

David Hammen's ответ правильный (double zmat[N+1][N+1]; слишком большой для стека). Тем не менее, я чувствую необходимость бросить в свои два цента о вашем использовании.

Двойной цикл излишне подробный и медленный. Хуже того, использование coeffref на каждом элементе матрицы фактически делает матрицу эффективной плотной. В documentation для coeffRef он говорит:

Если элемент не существует, то он вставляется через вставку (Index, Индекс) функции, которая сама по себе превращает матрицу в не сжатом виде, если это не так.
Это операция O (log (nnz_j)) (бинарный поиск) плюс стоимость функции вставки (индекс, индекс), если элемент еще не существует.

Это означает, что он не только подробен, но и добавит к вашим требованиям к памяти и может стать узким местом. Вместо этого вы можете использовать

MatrixXd::Map(&zmat[0], (N+1), (N+1)) = mat.toDense(); 

или

MatrixXd::Map(zmat, (N+1), (N+1)) = mat.toDense(); // double zmat = new ... 

Это не только более удобным для чтения, но гораздо более эффективным, а также.

+0

Это не сработает. Двойной цикл необходим, потому что 'mat.coeffRef (i, j)' является разреженной матрицей. –

+0

Ой, пропустил это. Исправлена. –

Смежные вопросы