Порядок хранения данных
Существуют два разных порядка хранения данных для матриц и двумерных массивов: по столбцам и по строкам. Эта страница объясняет эти порядки хранения и как указать, какой из них следует использовать.
Хранение по строкам и по столбцам
Элементы матрицы образуют двумерную сетку. Однако при хранении матрицы в памяти элементы должны быть каким-то образом расположены линейно. Существует два основных способа сделать это: по строкам и по столбцам.
Мы говорим, что матрица хранится в порядке по строкам, если она хранится строка за строкой. Сначала хранится вся первая строка, затем вся вторая и так далее. Рассмотрим, например, матрицу
\[ A = \begin{bmatrix} 8 & 2 & 2 & 9 \\ 9 & 1 & 4 & 4 \\ 3 & 5 & 4 & 5 \end{bmatrix}. \]
Если эта матрица хранится в порядке по строкам, то элементы выстраиваются в памяти следующим образом:
8 2 2 9 9 1 4 4 3 5 4 5
С другой стороны, матрица хранится в порядке по столбцам, если она хранится столбец за столбцом, начиная с целого первого столбца, за которым следует весь второй столбец и так далее. Если вышеуказанная матрица хранится в порядке по столбцам, она выстраивается следующим образом:
8 9 3 2 1 5 2 4 4 9 4 5
Этот пример проиллюстрирован следующим кодом Eigen. Он использует функцию PlainObjectBase::data(), которая возвращает указатель на местоположение в памяти первого элемента матрицы.
| Пример | Вывод |
|---|---|
Matrix<int, 3, 4, ColMajor> Acolmajor;
Acolmajor << 8, 2, 2, 9,
9, 1, 4, 4,
3, 5, 4, 5;
cout << "The matrix A:" << endl;
cout << Acolmajor << endl << endl;
cout << "In memory (column-major):" << endl;
for (int i = 0; i < Acolmajor.size(); i++)
cout << *(Acolmajor.data() + i) << " ";
cout << endl << endl;
Matrix<int, 3, 4, RowMajor> Arowmajor = Acolmajor;
cout << "In memory (row-major):" << endl;
for (int i = 0; i < Arowmajor.size(); i++)
cout << *(Arowmajor.data() + i) << " ";
cout << endl;
|
The matrix A: 8 2 2 9 9 1 4 4 3 5 4 5 In memory (column-major): 8 9 3 2 1 5 2 4 4 9 4 5 In memory (row-major): 8 2 2 9 9 1 4 4 3 5 4 5 |
Порядок хранения в Eigen
Порядок хранения матрицы или двумерного массива можно установить, указав параметр шаблона Options для Matrix или Array. Как объясняет Класс матрицы, шаблон класса Matrix имеет шесть параметров шаблона, из которых три обязательны (Scalar, RowsAtCompileTime и ColsAtCompileTime) и три необязательны (Options, MaxRowsAtCompileTime и MaxColsAtCompileTime). Если параметр Options установлен в RowMajor, то матрица или массив хранятся в порядке по строкам; если он установлен в ColMajor, то хранятся в порядке по столбцам. Этот механизм используется в вышеприведённой программе Eigen для указания порядка хранения.
Если порядок хранения не указан, то Eigen по умолчанию хранит элементы в порядке по столбцам. Это также происходит, если используется один из удобных псевдонимов типов (Matrix3f, ArrayXXd, и т.д.).
Матрицы и массивы, использующие один порядок хранения, могут быть присвоены матрицам и массивам, использующим другой порядок хранения, как происходит в приведенной выше программе, когда Arowmajor инициализируется с помощью Acolmajor. Eigen автоматически переупорядочит элементы. Более обще, матрицы в порядке по строкам и по столбцам могут быть смешаны в выражении, как нам нужно.
Какой порядок хранения выбрать?
Итак, какой порядок хранения следует использовать в вашей программе? На этот вопрос нет простого ответа; это зависит от вашей задачи. Вот несколько моментов, которые следует учитывать:
- Ваши пользователи могут ожидать, что вы будете использовать определённый порядок хранения. Кроме того, вы можете использовать другие библиотеки, помимо Eigen, и эти другие библиотеки могут ожидать определённый порядок хранения. В этих случаях проще всего и быстрее всего использовать этот порядок хранения во всей вашей программе.
- Алгоритмы, которые проходятся по матрице по строкам, будут работать быстрее, когда матрица хранится в порядке по строкам из-за лучшей локализации данных. Аналогично, проход по столбцам быстрее для матриц в порядке по столбцам. Может быть полезно немного поэкспериментировать, чтобы выяснить, что быстрее для вашей конкретной задачи.
- По умолчанию в Eigen используется порядок по столбцам. Естественно, большая часть разработки и тестирования библиотеки Eigen выполняется с матрицами в порядке по столбцам. Это означает, что, хотя мы стремимся прозрачно поддерживать порядки хранения по строкам и по столбцам, библиотека Eigen может работать лучше всего с матрицами в порядке по столбцам.
© Eigen.
Licensed under the MPL2 License.
https://eigen.tuxfamily.org/dox/group__TopicStorageOrders.html