Наиболее эффективный вариант построения трехмерных структур с использованием собственных матриц.

Мне нужна трехмерная структура матрицы/массива в моем коде, и сейчас я полагаюсь на Eigen как для своих матриц, так и для векторов.

Прямо сейчас я создаю 3D-структуру, используя new:

MatrixXd* cube= new MatrixXd[60];
for (int i; i<60; i++) cube[i]=MatrixXd(60,60);

и для доступа к значениям:

double val;
MatrixXd pos;
for (int i; i<60; i++){
    pos=cube[i];
    for (int j; j<60; j++){
        for (int k; k<60; k++){
            val=pos(j,k);
            //...
        }
    }
}

Однако сейчас эта часть кода работает очень медленно, что наводит меня на мысль, что это может быть не самый эффективный способ. Есть ли альтернативы?


person joaocandre    schedule 13.06.2013    source источник
comment
Если вам действительно нужна трехмерная матрица, то нет способа использовать этот вложенный цикл. С матрицей 60x60x60 у вас есть 216 000 значений, которые вы сохраняете, поэтому это всегда будет относительно медленно. Какую проблему ты пытаешься решить? Может есть способ решить без 3д матрицы.   -  person Egg    schedule 14.06.2013
comment
Я вычисляю матрицу NxN для определенного количества временных шагов, и мне нужно хранить данные для каждого момента, чтобы в конце я мог выполнить средневзвешенное значение. Мой вопрос был больше об использовании new - точнее, если нет других типов массива (может быть, в буст-библиотеках), которые можно использовать для стекирования нескольких MatrixXd.   -  person joaocandre    schedule 14.06.2013


Ответы (3)


Хотя он был недоступен, когда был задан вопрос, Eigen уже некоторое время предоставляет модуль Tensor. Он все еще находится на стадии «не поддерживается» (это означает, что API может измениться), но базовая функциональность должна быть в основном стабильной. Документация разбросана по здесь и здесь.

person chtz    schedule 03.12.2016

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

MatrixXd A(60*60,60);

а затем получить к ним доступ с помощью блочных операций.

A0 = A.block<60,60>(0*60,0);
...
A5 = A.block<60,60>(5*60,0);
person FlavioG    schedule 01.02.2017

Альтернативой является создание очень большого куска памяти и отображение из него собственных матриц:

double* data = new double(60*60 * 60*60*60);

Map<MatrixXd> Mijk(data+60*(60*(60*k)+j)+i), 60, 60);

На этом этапе вы можете использовать Mijk как объект MatrixXd. Однако, поскольку это не тип MatrixXd, если вы хотите передать его функции, ваша функция должна:

  • иметь форму foo(Map<MatrixXd> mat)
  • быть шаблонной функцией: template<typename Der> void foo(const MatrixBase<Der>& mat)
  • возьмите объект Ref<MatrixXd>, который может обрабатывать как объекты Map<>, так и Matrix<>, не будучи шаблонной функцией и без копий. (документ)
person ggael    schedule 14.06.2013