Я использую функцию внешней библиотеки, которая получает на вход тип:&mut [&mut [f32]]
, который должен представлять собой двумерный массив фиксированных размеров.
Для повышения производительности я хотел бы создать одномерный массив, чтобы все данные постоянно находились в памяти, и преобразовать их в указанную выше форму.
Однако из-за отсутствия опыта работы с Rust у меня мало проблем, и мне интересно, каким «путем Rust» можно достичь моей цели.
Один из способов, о котором я мог подумать, — это создать новый Vec
, повторить одномерный массив и перенести в него каждый фрагмент, но это похоже на пустую трату памяти.
Заранее спасибо.
Почему одномерный массив будет более производительным в вашем случае? Как именно вы по-другому организуете массив в памяти?
К вашему сведению, функции обычно не должны принимать &mut [&mut [T]]
, они должны принимать &mut [impl AsMut<[T]>]
. Если это ваш единственный вариант, то ваша идея создать новый Vec
хороша, и если под «исправленным» вы подразумеваете исправленные во время компиляции, то вы можете поместить их в массив.
Если у вас есть данные в одном непрерывном векторе, вы можете использовать chunks_exact_mut для получения итератора над каждым изменяемым подсрезом, но вам придется собрать это в другой Vec
, чтобы передать полученный срез в библиотека.
@Codebling, возможно, я ошибаюсь, но если я создам 2d-массив, гарантированно ли он будет лежать в том же фрагменте памяти?
@eggyal, не могли бы вы опубликовать ответ с примером вашего решения?
barak1412 да! 1D целых чисел содержит все целые числа подряд. «2D-массив» на самом деле представляет собой просто 1D-массив 1D-массивов. Когда вы спрашиваете, всегда ли он будет находиться в одном и том же участке памяти, ответ — да. Если вы спрашиваете, какие элементы будут смежными, элементы каждой «строки» будут смежными, и каждая строка также будет смежной. Если вам нужен конкретный макет, который вам нужен, вы можете оптимизировать его дальше.
По моему скромному мнению, для каждого проекта существует планка производительности, и пока кто-то ожидает, что его код будет оставаться выше этого уровня производительности, ему следует сосредоточиться на чистом и удобном в сопровождении коде, прежде чем сосредоточиться на оптимизации.
@Codebling Я согласен с тобой. Полезно знать о 2d-массиве, спасибо!
Вы не можете превратить Vec<f32>
в &mut [&mut [f32]]
, но вы можете дешево построить &mut [&mut [f32]]
из Vec<f32>
, сначала превратив его в &mut [f32]
, а затем просто обернув его в другой &mut []
.
fn main() {
let mut v = vec![1.0, 2.0, 3.0];
let inner = &mut *v;
add(&mut [inner], 10.0);
println!("{v:?}");
// [11.0, 12.0, 13.0]
}
fn add(arr: &mut [&mut [f32]], addend: f32) {
for inner in arr {
for x in inner.iter_mut() {
*x += addend;
}
}
}
Как срез, сгенерированный таким образом, «представляет собой двумерный массив фиксированных размеров». которые отличаются от (1, N)?
Если у вас есть данные в одном непрерывном срезе (например, в Vec
), вы можете использовать chunks_exact_mut для получения итератора по каждому изменяемому подсрезу, но вам придется собрать это в (другой) Vec
чтобы передать полученный фрагмент в библиотеку. Например:
/// Given the row-first two-dimensional array represented by
/// `contiguous_rows_of_cols`, return (in order) each row as a subslice.
fn to_vec_of_slices<T>(contiguous_rows_of_cols: &mut [T], cols: usize) -> Vec<&mut [T]> {
contiguous_rows_of_cols.chunks_exact_mut(cols).collect()
}
Вы не можете преобразовать
vec<f32>
в&mut [&mut [f32]]
, поскольку данные имеют неправильную форму. Например, вы можете использоватьVec<&mut [f32]>
, вероятно, это будет эффективно, только если внешний размер небольшой. Вы можете использовать такую библиотеку , которая определяет для вас такие представления.