Как загрузить в стек все записи Vec‹T› произвольной длины?

В настоящее время я работаю с векторами и пытаюсь убедиться, что у меня есть массив моего вектора в стеке. Я не могу вызвать Vec::into_boxed_slice, так как я динамически выделяю место в моем Vec. Это вообще возможно?

Прочитав Растономикон о как реализовать Vec, кажется обходить указатели в куче, разыменовывая каждую запись. Я хочу разбить Vec записей из кучи в стек для быстрого доступа.


person Bots Fab    schedule 02.02.2021    source источник
comment
Вы, вероятно, неправильно поняли какую-то часть Рустономикона, поскольку Vecs — это непрерывные выделения памяти. Конечно, сами элементы могут каким-то образом быть блоками или указателями. В любом случае, было бы неплохо связать то, что вы читаете на Растономиконе, и показать, какие T вы ожидаете, так что, возможно, ответ может развеять ваше замешательство.   -  person Caesar    schedule 02.02.2021
comment
doc.rust-lang.org/nomicon/vec.html doc.rust-lang.org/nomicon/vec-layout.html из doc.rust-lang.org/std/vec/struct.Vec.html ..Vec никогда не будет выполнять небольшую оптимизацию, при которой элементы фактически хранятся в стеке по двум причинам:.. из-за этого я склонен полагать, что все значения хранятся в куче. учитывая итеративную реализацию в «номиконе», я считаю, что он должен разыменовываться при каждом приращении указателя, который упоминается выше в куче. Я ожидаю, что общие T будут конкретными   -  person Bots Fab    schedule 02.02.2021
comment
Ха нет. Потому что стек можно вытолкнуть, и он должен иметь лучшую локализацию кеша. Я только когда-либо читал кучу, реализованную как деревья и хэш-карты, которые разбросаны по памяти и так, что время поиска было хуже, поскольку каждое разыменование должно искать эти структуры данных (которые могут быть фрагментированы) вместо упорядоченного адреса данных стека структура.   -  person Bots Fab    schedule 02.02.2021
comment
Данные Vec всегда являются непрерывными (непрерывный расширяемый тип массива), который лучше всего подходит для локальности. Вы, кажется, запутались между стеком и кучей типов данных и стеком и кучей областей памяти. Я призываю вас исследовать разницу; Я предполагаю, что это прояснит ситуацию.   -  person Shepmaster    schedule 02.02.2021
comment
.... буквально поэтому их называют стеком и кучей.   -  person Bots Fab    schedule 02.02.2021
comment
Шепмастер, как обычно, прав. Подобная куче природа распределения памяти вступает в игру только тогда, когда вы выделяете или освобождаете память — вам не нужно проходить кучу (структуру данных) каждый раз, когда вы используете что-то, что хранится в куча (общий термин для динамически выделяемой памяти, которая может быть или не быть структурирована как реальная куча). Когда у вас есть указатель на данные (который представляет собой Vec), не имеет значения, находятся ли они в стеке или в куче.   -  person trentcl    schedule 02.02.2021
comment
Адресация на основе стека выполняется с помощью целочисленной арифметики, вычисляемой на основе относительной позиции счетчика команд. Память кучи адресуется путем поиска в дереве (или другой структуре данных с разреженной поддержкой), это связано с тем, что после выделения память фрагментируется, а адресация не зависит друг от друга. Пожалуйста, поправьте меня, если я все еще ошибаюсь. stackoverflow.com/questions/24057331/ stackoverflow.com/questions/51928246/   -  person Bots Fab    schedule 02.02.2021
comment
Адресация на основе стека выполняется с помощью целочисленной арифметики, вычисляемой на основе указателя стека (а не счетчика программы). Память кучи адресуется с помощью целочисленной арифметики, вычисляемой из базового указателя адресуемого объекта. Картофель/Потато. Обход кучи происходит только при выделении или освобождении памяти, а не при обычной адресации (при условии, что распределитель использует структуру кучи, чего может и не быть).   -  person Jmb    schedule 02.02.2021
comment
Спасибо за разъяснение СП. Как можно разрешить набор произвольных адресов с той же скоростью, что и набор относительных адресов? Можете ли вы решить вопрос, указанный в разделе «Доступ» в первом ответе: stackoverflow.com/questions/24057331/   -  person Bots Fab    schedule 02.02.2021
comment
Нет набора произвольных адресов. Vec содержит простой указатель на данные, вот и все. Никакого разрешения, только одно разыменование, точно так же, как с данными (произвольного размера) в стеке.   -  person user4815162342    schedule 02.02.2021
comment
Весь смысл стека в том, что он непрерывен. Зачем вообще две структуры данных? почему бы просто не выделить в стеке? Виртуализация и управление памятью операционных систем вместе с планировщиком решают проблему подгонки компьютерных ресурсов, используя две очень разные методологии в структурах данных. Если что-то не изменилось с тех пор, как я в последний раз изучал это, мы имеем в виду не Vec, а то, что глобальный распределитель делает за кулисами, что является вызовом операционной системы для несмежной памяти с динамическим размером.   -  person Bots Fab    schedule 02.02.2021
comment
Смотри, это так. Представьте, что вы работаете в библиотеке. Время от времени люди будут приходить и просить у вас книгу. Большую часть времени они хотят прочитать один из новых выпусков, например, последнюю книгу Мэгги Холт или что-то в этом роде. Верно? Итак, у вас есть полка, полная новых выпусков, возможно, упорядоченных по дате. Это стек. Но было бы непрактично и бесполезно сортировать всю библиотеку по дате, поэтому у вас есть другие книги, организованные по темам в соответствии с LCSH или чем-то еще. Это куча. Аналогия несовершенна, но потерпите меня. Теперь иметь указатель на что-то — это все равно, что знать, на какой полке это находится — (1/)   -  person trentcl    schedule 03.02.2021
comment
если вы уже знаете, где находится книга, ее поиск займет примерно столько же времени, независимо от того, находится ли она в разделе новых выпусков или нет. Более того, сама книга представляет собой единый непрерывный кусок страниц, независимо от того, на какой полке она находится, поэтому, как только вы ее нашли, на чтение уходит одинаковое количество времени, независимо от того, на какой полке вы находитесь. нашел его, потому что все страницы расположены рядом друг с другом по порядку. Точно так же Vec — это целая книга, фрагмент страниц, расположенных в памяти непрерывно, а не набор страниц, разбросанных по всей библиотеке. Перенос книги из (2/)   -  person trentcl    schedule 03.02.2021
comment
куча в стек не заставит вас читать ее быстрее, потому что, когда у вас есть книга, уже не имеет значения, как вы туда попали. Чтобы приблизить аналогию к реальной стопке и куче, представьте, что вместо этого вы управляете бизнесом по хранению книг, поэтому вместо сортировки по теме и дате вы сортируете все книги по размеру и весу и вместо того, чтобы искать их, когда клиент запрашивает определенного названия, вы ищете книгу только тогда, когда приходит владелец этого конкретного тома и хочет ее удалить. (3/3)   -  person trentcl    schedule 03.02.2021
comment
stackoverflow.com/questions/45753923/ Это мне очень помогло. Память непрерывна, вы не можете победить vec, если не хотите удалить дополнительную емкость с помощью сжатия. всем спасибо.   -  person Bots Fab    schedule 06.02.2021


Ответы (1)


Вы можете использовать функцию unsized_locals в nightly Rust:

#![feature(unsized_locals)]

fn example<T>(v: Vec<T>) {
    let s: [T] = *v.into_boxed_slice();
    dbg!(std::mem::size_of_val(&s));
}

fn main() {
    let x = vec![42; 100];
    example(x); // Prints 400
}

Смотрите также:


Я не могу позвонить Vec::into_boxed_slice, так как я динамически выделяю место в моем Vec

Что вы можете.

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

Для доступа к каждому члену в Vec требуется разыменование памяти. Для доступа к каждому члену массива требуется разыменование памяти. Здесь нет существенной разницы в скорости.

для быстрого доступа

Я сомневаюсь, что это будет быстрее, чем прямой доступ к данным в файле Vec. На самом деле, я не удивлюсь, если он будет медленнее, поскольку вы его копируете.

person Shepmaster    schedule 02.02.2021
comment
У меня сложилось впечатление, что разыменование из стека будет быстрее, чем структура данных кучи. Я лениво реализую алгоритм, который успевает асинхронно выделять память во время обработки, поэтому подумал, что это может сэкономить некоторое время. Спасибо, мне не удалось заставить компилятор разрешить мне .into_boxed_slice, потому что [Cell‹T›] не реализует трейт Sized. Я предположил, что это произошло из-за отсутствия [Cell‹T›; n] явно объявлено, так как размер T был задан. Я попробую еще раз и прочитаю на ночь. - person Bots Fab; 02.02.2021
comment
@BotsFab начальное удаление ссылки будет медленнее, потому что стек находится в кеше, а расположение кучи - нет, но загрузка vec будет кэшировать его в любом случае. За исключением того, что, загружая кеш в стек, вы раздуваете кеш и, возможно, сам код (не уверен насчет неразмерных локальных переменных, но я знаю, что в C VLA приводит к абсолютному мусорному коду). - person Masklinn; 02.02.2021
comment
@Masklinn VLA относительно малы и хорошо помещаются в кеш. Это древовидная структура, в которой ребра из заданного узла — это то, что помещается в стек, и я планирую ограничить ребра в конфигурации или автоматически, чтобы они помещались в строки кэша, если это необходимо). Это настолько крайний случай, что, вероятно, не по теме, но, похоже, вызывает оправданный интерес. Эта мелочь важна, потому что это алгоритм машинного обучения, который масштабируется (и для моей сентиментальной ценности скорости). - person Bots Fab; 02.02.2021
comment
@BotsFab, если они поместятся в кеш, они подойдут так же хорошо, как и Vec, которыми они уже являются, в лучшем случае это не должно иметь никакого значения. Проблема с динамическим выделением стека заключается в том, что компилятор генерирует некачественный код. - person Masklinn; 02.02.2021
comment
@Masklinn Я не знаком с генератором кода из динамического распределения стека, я надеялся, что все это будет помещено в фрагмент, который можно будет быстро извлечь относительно загрузки и инструкций регистра. Спасибо за ваше понимание. - person Bots Fab; 02.02.2021
comment
TBF Я не знаю, имеет ли это ту же проблему, что и VLA, но я знаю, что одна из причин, по которой VLA были в конечном итоге удалены за пределы ядра Linux (и различных других кодовых баз), заключается в том, что они приводят к действительно плохому коду. - person Masklinn; 02.02.2021