Предварительное выделение памяти в MATLAB à la std :: vector :: reserve (n) - PullRequest
5 голосов
/ 13 февраля 2012

Так что reserve очень полезно, когда вы имеете приблизительное представление о ваших требованиях к размеру. Кто-нибудь знает подобный метод для предварительного выделения массивов в MATLAB?

Меня не очень интересуют хакерские (но эффективные) методы, подобные следующим:

x = zeros(1000,1);
for i = 1:10000
    if i > numel(x)
       x = [x;zeros(size(x))];
    end
    x(i) = rand;
end
x(i+1:end) = [];

Ответы [ 3 ]

3 голосов
/ 13 февраля 2012

«Хакерский» способ - единственный способ сделать это. Тем не менее, вам не нужно проверять I <= цифра (х). Массив будет расширен автоматически (но без дублирования массива): </p>

x = zeros(1000,1);
for i = 1:10000
    x(i) = rand;
end
x(i+1:end) = [];

РЕДАКТИРОВАТЬ: для простоты, сохраняя удвоение массива, вы можете написать класс или просто несколько вспомогательных функций (ниже).

EDIT2: использование вспомогательных функций замедлит работу по сравнению с ручным взломом. В MATLAB 2010 это все еще намного быстрее, чем наивный рост. В MATLAB 2011 наивный подход на самом деле быстрее, предполагая, что эта версия имеет более разумное распределение. Возможно, это достаточно быстро, так что взломать не нужно вообще. Спасибо Эндрю Янке за указание на это.

function listtest()
    n = 10000;
    l = new_list();
    for i=1:n
        l = list_append(l, i);
    end
    a = list_to_array(l);
end

function l = new_list()
    l = [0 0];
end
function l = list_append(l, e)
    if l(1)+1 == length(l)
        l(length(l)*2) = 0;
    end
    l(1) = l(1)+1;
    l(l(1)+1) = e;
end
function a = list_to_array(l)
    a = l(2:1+l(1));
end

РЕДАКТИРОВАТЬ (от AndrewJanke)

Вот код для сравнения скорости реализации.

function manual_reserve_example(n)
x = zeros(1000,1);
for i = 1:n
    if i > numel(x)
       x = [x;zeros(size(x))];
    end
    x(i) = i;
end
x(i+1:end) = [];
end

function naive_growth(n)
x = 0;
for i = 1:n
    x(i) = i;
end
end

function compare_them(n)
fprintf('Doing %d elements in Matlab R%s\n', n, version('-release'));
tic;
naive_growth(n);
fprintf('%30s  %.6f sec\n', 'naive_growth', toc);
tic;
manual_reserve_example(n);
fprintf('%30s  %.6f sec\n', 'manual_reserve', toc);
tic;
listtest(n);
fprintf('%30s  %.6f sec\n', 'listtest', toc);
end
1 голос
/ 13 февраля 2012

Самое чистое решение для приведенного вами примера - итерация в обратном направлении.

for i = 10000:-1:1
    x(i) = rand;
end

Это не работает в тех случаях, когда конечный размер на самом деле неизвестен, но чаще мне пригодилсячем я ожидал.


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

Чистое решение состоит в том, чтобы обернуть класс Matlab вокруг соответствующего алгоритма изменения размера вектора, а затем использовать этот класс.Я не знаю ни одной причины, по которой такой класс не мог бы быть создан, но я никогда не сидел и не пытался его реализовать.(Мне любопытно, если где-нибудь уже есть пример обмена файлами.)

0 голосов
/ 13 февраля 2012

Существует способ предварительно выделить память для структуры в MATLAB 7.6 (R2008a) с помощью команд STRUCT и REPMAT.

ПРИМЕР 1: структура с двумя полями

s.field1 s.field2

s = struct('field1',cell(1),'field2',cell(1));

ПРИМЕР 2: Структура с полем с подполем

s.field1.subfield

s = struct('field1',struct('subfield',cell(1)));

ПРИМЕР 3: Массив структур

v (1) .field1 ... v (100) .field1

s = struct('field1',cell(1));
v = repmat(s,100,1);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...