Что такое пошаговый массив?

Существует также аналог, который называется массивом плотности. Что это значит? Я сделал некоторые поиски, но не получил точной информации.


person Thomson    schedule 04.08.2011    source источник


Ответы (6)


Шагать — значит «делать большие шаги».

thefreedictionary.com/stride

Для массива это будет означать, что присутствуют только некоторые элементы, например каждый 10-й элемент. Затем вы можете сэкономить место, не сохраняя пустые элементы между ними.

Плотным массивом будет тот, в котором присутствуют многие, если не все элементы, поэтому между элементами нет пустого пространства.

person Bo Persson    schedule 04.08.2011
comment
Термин, который я знаю, - разреженный массив (на самом деле я слышал о разреженных матрицах или разреженных векторах, особенно в числах). Является ли массив с шагом синонимом разреженного массива? - person Kos; 04.08.2011
comment
Разреженный массив, вероятно, более распространенный термин, но, возможно, с немного другим значением (не регулярное расстояние между элементами?). Термин шаг появляется в разделе <valarray> стандарта C++. - person Bo Persson; 04.08.2011
comment
@Kos: разреженный массив может иметь более общие формы. Это действительно частный случай разреженного массива. - person Alexandre C.; 04.08.2011
comment
@Alexandre, нет, массив с шагом может иметь шаг, не кратный размеру элемента. И эти понятия различаются логически - person unkulunkulu; 04.08.2011
comment
@unkulunkulu: например, когда вы используете BLAS уровня 1/2, вы передаете шаг массива в качестве аргумента, и это число. В большинстве случаев шаг предполагает постоянный шаг, который представляет собой количество элементов, которые нужно пропустить, плюс один. - person Alexandre C.; 04.08.2011
comment
@Alexandre, то, что вы сказали, верно (хотя эта плюс одна часть подозрительна), но это не дает аргумента для утверждения, что массив с шагом является частным случаем разреженного (что неверно). В MPI также есть типы массивов с шагом, и шаг постоянен, да. Так что это не имеет ничего общего с разреженными массивами. - person unkulunkulu; 04.08.2011
comment
@unkulunkulu: Это зависит от формата. Я мог бы хранить свой массив в форме (индекс, значение), и в этом случае { (1, 0,42), (2000, 7), (2001, 53,2)} является разреженным массивом, но я бы не хотел вызывать это массив с шагом. Что касается плюса, это просто арифметика указателей: шаг = 1 означает плотный массив. Это количество элементов, на которое вы увеличиваете текущий указатель, чтобы перейти к следующему. - person Alexandre C.; 04.08.2011
comment
@ Александр, ты ошибаешься, прочитай Джонатана и мои ответы о том, что такое массив с шагом. Между его элементами нет нулей. И еще раз, шаг не равен 1, он может быть не кратным размеру элемента, это просто расстояние между последовательными элементами массива. Согласен, кто-то может вывести свои определения, исходя из значения слова шаг, но в традиционном смысле это нельзя считать частным случаем разреженного массива (где цель — уменьшить потребление памяти, когда большинство элементов равны нулю). - person unkulunkulu; 04.08.2011
comment
Я согласен, я не думаю, что этот ответ должен быть принятым. В документах numpy/blas/lapack/eigen есть отличные (правильные) описания плотных матриц, где вы можете шагать по измерению с определенными шагами длины в пространстве плоского массива. - person meawoppl; 09.05.2017

Скажем, у вас есть структура

struct SomeStruct {
    int someField;
    int someUselessField;
    int anotherUselessField;
};

и массив

struct SomeStruct array[10];

Затем, если вы посмотрите на все someField в этом массиве, их можно считать массивом сами по себе, но они не занимают последовательные ячейки памяти, так что этот массив шагает. шаг здесь равен sizeof(SomeStruct), то есть расстоянию между двумя последовательными элементами массива с шагом.

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

Шаговый массив является обобщением обычных (плотных) массивов, когда stride != sizeof(element).

person unkulunkulu    schedule 04.08.2011
comment
Ну вообще-то говорят, что strides может быть неконстантным, я проглядел :( - person unkulunkulu; 04.08.2011
comment
Так что я снова в замешательстве. Если разница между разреженным и шагом не в том, что расстояния равны или нет, то что? - person Kos; 04.08.2011
comment
@Kos, это довольно логично: разреженный массив просто сокращает использование памяти (и иногда сложность алгоритма), перечисляя только ненулевые элементы массива вместе с их индексами, в то время как пошаговый массив - это способ сказать, где в памяти находятся элементы расположены, когда они не расположены рядом. - person unkulunkulu; 04.08.2011
comment
Это то, что Википедия называет шагом массива. Однако в таких языках, как C или C++, это неинтересное свойство; это просто размер элементов массива. Упомянутый язык - PL/1. Я не нахожу эту страницу убедительной, хотя у меня нет конкретных контрданных, которые были бы необходимы для ее редактирования. ответ от FireFly также ссылается на эту страницу. - person Jonathan Leffler; 14.11.2015

Если вы хотите работать с подмножеством двумерного массива, вам нужно знать «шаг» массива. Предположим, у вас есть:

int array[4][5];

и вы хотите работать с подмножеством элементов, начиная с массива [1] [1] и заканчивая массивом [2,3]. Наглядно это ядро ​​​​диаграммы ниже:

+-----+-----+-----+-----+-----+
| 0,0 | 0,1 | 0,2 | 0,3 | 0,4 |
+-----+=====+=====+=====+-----+
| 1,0 [ 1,1 | 1,2 | 1,3 ] 1,4 |
+-----+=====+=====+=====+-----+
| 2,0 [ 2,1 | 2,2 | 2,3 ] 2,4 |
+-----+=====+=====+=====+-----+
| 3,0 | 3,1 | 3,2 | 3,3 | 3,4 |
+-----+-----+-----+-----+-----+

Чтобы точно получить доступ к подмножеству массива в функции, вам нужно сообщить вызываемой функции шаг массива:

int summer(int *array, int rows, int cols, int stride)
{
    int sum = 0;
    for (int i = 0; i < rows; i++)
        for (int j = 0; j < cols; j++)
            sum += array[i * stride + j];
    return(sum);
}

и вызов:

int sum = summer(&array[1][1], 2, 3, 5);
person Jonathan Leffler    schedule 04.08.2011

Я добавляю еще один ответ здесь, так как я не нашел ни один из существующих удовлетворительным.

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

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

Шаговые массивы

Компиляция APL в JavaScript объясняет массивы с шагом как способ представления многомерных массивов как с данными, так и с шагом, в отличие от типичное «прямоугольное» представление массивов, которое предполагает неявный шаг, равный 1. Оно допускает как положительный, отрицательный, так и нулевой шаг. Почему? Это позволяет многим операциям изменять только шаг и форму, а не базовые данные, что позволяет эффективно манипулировать большими массивами.

Преимущество такого пошагового представления становится очевидным при работе с большими объемами данных. Такие функции, как транспонирование (⍉⍵), реверсирование (⌽⍵) или удаление (⍺↓⍵), могут повторно использовать массив данных и заботятся только о том, чтобы придать результату новую форму, шаг и смещение. Скаляр измененной формы, например. 1000000⍴0, может занимать только постоянный объем памяти, используя тот факт, что шаги могут быть равны 0.

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

person FireFly    schedule 08.11.2014

Возможность 1: Stride описывает буферный массив для чтения оптимизированного массива.

При использовании метода для сохранения многомерных массивов в линейном хранилище. Шаг описывает размер в каждом измерении буфера, который поможет вам прочитать этот массив. Изображение взято с сайта Nd4j (дополнительная информация о Stride)

Шаг как буфер массива

Вариант 2 (нижний уровень): Шаг — это расстояние между смежными элементами массива.

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

Это полезно на низком уровне (оптимизация длины слова, перекрывающиеся массивы, оптимизация кеша). См. википедию.

person corlaez    schedule 09.08.2017

В высокооптимизированном коде одним из довольно распространенных приемов является вставка заполнения в массивы. Это означает, что N-й логический элемент больше не находится по смещению N*sizeof(T). Причина, по которой это может быть оптимизацией, заключается в том, что некоторые кэши ограничены ассоциативностью. Это означает, что они не могут кэшировать как массив[i], так и массив[j] для некоторых пар i,j. Если алгоритм, работающий с плотным массивом, будет использовать много таких пар, вставка некоторого дополнения может уменьшить это.

Распространенным случаем, когда это происходит, является обработка изображений. Изображение часто имеет ширину строки 512 байт или другое «двоичное круглое число», и многие процедуры обработки изображений используют окрестность пикселя 3x3. В результате вы можете получить довольно много вытеснений кеша на некоторых архитектурах кеша. Вставляя «странное» количество поддельных пикселей (например, 3) в конце каждой строки, вы изменяете «шаг» и между соседними строками возникает меньше помех в кеше.

Это очень зависит от процессора, поэтому здесь нет общих советов.

person MSalters    schedule 04.08.2011