почему время доступа к данным, хранящимся в ячейках, короче, чем в матрицах? - PullRequest
4 голосов
/ 09 ноября 2011

Я имею дело с очень большими данными в matlab и использовал для хранения этих данных в матрицах.Я имел обыкновение хранить свои данные по строкам, но поскольку Matlab хранит данные по столбцам, я понимаю, что изменение формы моей матрицы, поэтому индексирование по столбцам делает обработку быстрее.Вот пример того, что я имею в виду:


общие параметры

nbr_channels = 20;
nbr_samples_per_channel = 3200000;
fake_data = randn(1, nbr_samples_per_channel);
ROI = 1200000 : 2800000;

назначить данные по строке

data = nan(nbr_channels, nbr_samples_per_channel);
tic; 
for j = 1 : nbr_channels
    data(j, 1:nbr_samples_per_channel) = fake_data; 
end; 
toc;

% Elapsed time is 1.476525 seconds.

возврат данных из матрицы строк

tic; 
for j = 1 : nbr_channels
    bla = data(j, ROI); 
end; 
toc;

% Elapsed time is 0.572162 seconds.

возврат всех данных из матрицы строк

tic; 
for j = 1 : nbr_channels
    bla = data(j, :); 
end; 
toc;

% Elapsed time is 0.589489 seconds.

назначение данных постолбец

data = nan(nbr_samples_per_channel, nbr_channels);
tic; 
for j = 1 : nbr_channels
    data(1:nbr_samples_per_channel, j) = fake_data; 
end; 
toc;

% Elapsed time is 0.299682 seconds.

возврат данных из матрицы столбцов

tic; 
for j = 1 : nbr_channels
    bla = data(ROI, j); 
end; 
toc;

% Elapsed time is 0.260824 seconds.

возврат всех данных из матрицы столбцов

tic; 
f    or j = 1 : nbr_channels
    bla = data(:, j); 
end; 
toc;

% Elapsed time is 0.092983 seconds.

Сводка Part1:

Как мы видим, доступ к данным по столбцам сокращает время обработки как минимум в два раза!

Но я не понимаю, почему клетки еще эффективнее!Посмотрите на этот пример:

назначить данные по ячейке

data = cell(1, nbr_samples_per_channel);
tic; 
for j = 1 : nbr_channels
    data{j} = fake_data; 
end; 
toc;

% Elapsed time is 0.000013 seconds.

вернуть данные из массива ячеек

tic; 
for j = 1 : nbr_channels
    bla = data{j}(ROI); 
end; 
toc;

% Elapsed time is 0.260294 seconds.

вернуть все данные из массива ячеек

tic; 
for j = 1 : nbr_channels
    bla = data{j}; 
end; 
toc;

% Elapsed time is 0.000022 seconds.

%%

Сводка Part2:

Это на несколько порядков быстрее, чем яв части 1.

Вопрос 1

Почему время доступа к данным, хранящимся в ячейках, меньше, чем в матрицах?

Вопрос 2

Работа с матрицами обычно проще, чем с ячейками, потому что с включенной матрицей можно сделать

my_matrix(100:20000, 1:3)

, но с ячейками я не могу этого сделать(насколько я знаю).Любые альтернативы о том, как вернуть определенные элементы из нескольких ячеек одновременно?

1 Ответ

3 голосов
/ 10 ноября 2011

Вы видите разные времена, потому что вы не делаете эквивалентные вещи.Чтобы сравнить два ваших случая:

назначить данные по ячейке

  • Вы создаете вектор строки массива ячеек и вставляете длинную двойнуювектор для каждой ячейки

  • Каждая итерация цикла приводит к 1 назначению вектора в один слот в массиве ячеек

  • Есть 'nbr_samples_per_channel'число выполняемых назначений.

назначить данные по столбцу

  • вы проходите через столбцы матрицыи присвоение вектора каждому элементу в каждом столбце

  • Каждая итерация цикла, независимо от используемой сокращенной записи двоеточия: обозначения, разрешается во множество назначений.data (1: nbr_samples_per_channel, j) означает «nbr_samples_per_channel» назначения на одну итерацию.

  • в целом, вы выполняете 'nbr_samples_per_channel' * 'nbr_channels' всего назначений.

Чтобы выразить свою точку зрения, просто переписайте цикл без оператора двоеточия, чтобы визуализировать все назначения.

for j = 1 : nbr_channels    

    n = length(fake_data)

    data(1,     j) = fake_data(1); 
    data(2,     j) = fake_data(1); 

    ... etc ...

    data(n - 1, j) = fake_data(n-1); 
    data(n,     j) = fake_data(n); 

end

Итак, в заключение вы сравниваете две разные вещи, так что вы можетеНельзя сказать, что один действительно быстрее другого, потому что они не эквивалентны.

Если вы просто зацикливаетесь на двойном массиве и массиве ячеек и делаете регулярные присваивания ....

%% Setup samples and pre-allocate
numberOfSamples = 100000;

doubleData = nan(numberOfSamples, 1);
cellData = cell(numberOfSamples, 1);

randomValues = rand(numberOfSamples, 1);

%% Assign N number of values to a double array
tic; 
for idx = 1 : numberOfSamples
    data(numberOfSamples) = randomValues(idx);
end
doubleTime = toc;

%% Assign N number of values to a cell array
tic; 
for idx = 1 : numberOfSamples
    cellData{numberOfSamples} = randomValues(idx);
end
cellTime = toc;

disp(sprintf('Double Array: %f seconds', doubleTime));
disp(sprintf('Cell   Array: %f seconds', cellTime));

В итоге вы получите:

Double Array: 0.006073 seconds
Cell   Array: 0.032966 seconds

На ваш второй вопрос, это то, что вы пытаетесь сделать?

>> bigCell = {1 2 3 4; 5 6 7 8; 9 10 11 12; 13 14 15 16}

bigCell = 

    [ 1]    [ 2]    [ 3]    [ 4]
    [ 5]    [ 6]    [ 7]    [ 8]
    [ 9]    [10]    [11]    [12]
    [13]    [14]    [15]    [16]

>> subCell = bigCell(1:2, 3:4)

subCell = 

    [3]    [4]
    [7]    [8]

Обратите внимание, что подэлемент по-прежнему является ячейкой,Используя (), а не {} для доступа к ячейке, вы сохраняете ее как ячейку.

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