2015-08-12 2 views

ответ

2

В массиве массивов, массивы себя будут обладать теми же свойствами локальности, что и массив элементов, потому что этот случай ничем не отличается - здесь «элементы» представляют собой массивы. Однако, независимо от того, являются ли элементы каждого вспомогательного массива смежными в памяти элементам другого подматрица, зависит от реализации подматриц.

Поскольку вы не указали язык, я буду использовать синтаксис C++ для демонстрации, но это в основном языковой агностик, поскольку он касается аспектов аппаратного обеспечения. Если ваш массив массивов эквивалентен C++ std::vector<std::vector<int>> - который представляет собой гибкий контейнер контейнеров, который может расти/сокращаться по мере необходимости, каждый std::vector будет смежным в памяти по отношению к другим, но std::vector не содержит элементов. Скорее, это оболочка вокруг динамически выделенного массива, обычно содержащая несколько указателей на базовые данные. Это означает, что каждая обертка будет непрерывной, но элементы не обязательно будут. Вот это live demo, демонстрирующее это.

Однако рассмотрим случай, когда ваш массив массивов - это std::array<std::array<int,3>,2> - это просто массив из 2 элементов, где каждый элемент представляет собой массив фиксированного размера, 3, int. A std::array - это обертка вокруг массива C фиксированного размера, который не распределяется динамически, в отличие от его аналога std::vector. В этом случае вы получаете то же свойство локальности, что и для случая std::vector - каждый std::array смежн с передышкой на других, но здесь вы также получаете что-то большее. Поскольку std::array фактически содержит базовые данные, а не только несколько указателей на него, элементы каждой подматрицы также смежны относительно друг друга. Это тоже можно увидеть here.

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

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

+0

Очень круто, спасибо за ваш подробный ответ и ссылки. Я не был уверен, был ли этот вопрос агностиком языка, поэтому я не включил язык. Тем не менее, этот вопрос был вызван моим интересом к тому, как в памяти выделяются матрицы numpy по сравнению со списками/массивами. Является наиболее эффективным для памяти способом представления матрицы, а затем большим массивом 1d, с соответствующим методом класса, который отображает индексы массива в строки/столбцы матрицы? Является ли это так, как numpy представляет матрицы (numpy в основном написан на C)? В отличие от представления матрицы в виде массива массивов, где массивы представляют собой строки. – kernelmachine

+0

@SSG Рад, что я мог помочь! Что касается эффективности вашего вопроса, то, имея предсказуемый, линейный порядок доступа, где вы касаетесь непрерывной памяти, лучше с точки зрения кэширования и предварительной выборки, чем что-то вроде перемещения связанного списка. Переходя через некоторый источник numpy, кажется, что под крышками матрицы представлены базовым «char *», который указывает на массив необработанного хранилища.Из того, что я видел, numpy, похоже, использует описанную вами технику, которая представляет собой логически плоский массив 1D, к которому каждый элемент доступен, добавляя указатель. – Alejandro

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