В MATLAB у меня есть for loop
, у которого есть много взаимодействий, чтобы пройти и заполнить матрицу sparse
. Программа очень медленная, и я хотел бы оптимизировать ее, чтобы вскоре закончить. В двух строках я использую команду find
, и редактор MATLAB предупреждает меня, что использование logical indexing
вместо find
улучшит производительность. Мой код очень похож на тот, который представлен в newreader для mathworks, рекомендация для читателей mathworks , где есть вектор значений и вектор уникального значения, сгенерированный из него. Использует find
для получения индекса в уникальных значениях (для обновления значений в матрице). Короче говоря, код дан:
positions = find(X0_outputs == unique_outputs(j,1));
% should read
positions = X0_outputs == unique_outputs(j,1);
Но последняя строка - это не индекс, а вектор нулей и единиц.
У меня есть наглядный пример, составьте набор показателей; tt=round(rand(1,6)*10)
tt = 3 7 1 7 1 7
сделать уникальный вектор; ttUNI=unique(tt)
ttUNI = 1 3 7
Используйте find, чтобы получить индекс положения значения в наборе уникальных значений; find(ttUNI(:) == tt(1))
ans = 2
Сравните с использованием логического индексирования; (ttUNI(:) == tt(1))
ans =
0
1
0
Наличие значения 2
намного полезнее, чем этот двоичный вектор, когда мне нужно обновить индексы для матрицы. Для моей матрицы я могу сказать mat(find(ttUNI(:) == tt(1)), 4)
, и это работает. В то время как использование (ttUNI(:) == tt(1))
требует последующей обработки.
Есть ли аккуратный и эффективный способ сделать то, что нужно? Или использование find
неизбежно при таких обстоятельствах?
ОБНОВЛЕНИЕ : я добавлю сюда код, рекомендованный пользователем: @Jonas, чтобы лучше понять проблему, с которой я столкнулся, и сообщить о некоторых результатах инструмента профилировщика.
ALL_NODES = horzcat(network(:,1)',network(:,2)');
NUM_UNIQUE = unique(ALL_NODES);%unique and sorted
UNIQUE_LENGTH = length(NUM_UNIQUE);
TIME_MAX = max(network(:,3));
WEEK_NUM = floor((((TIME_MAX/60)/60)/24)/7);%divide seconds for minutes, for hours, for days and how many weeks
%initialize tensor of temporal networks
temp = length(NUM_UNIQUE);
%making the tensor a sparse 2D tensor!!! So each week is another replica of
%the matrix below
Atensor = sparse(length(NUM_UNIQUE)*WEEK_NUM,length(NUM_UNIQUE));
WEEK_SECONDS = 60*60*24*7;%number of seconds in a week
for ii=1:size(network,1)%go through all rows/observations
WEEK_NOW = floor(network(ii,3)/WEEK_SECONDS) + 1;
if(WEEK_NOW > WEEK_NUM)
disp('end of weeks')
break
end
data_node_i = network(ii,1);
Atensor_row_num = find(NUM_UNIQUE(:) == data_node_i)...
+ (WEEK_NOW-1)*UNIQUE_LENGTH;
data_node_j = network(ii,2);
Atensor_col_num = find(NUM_UNIQUE(:) == data_node_j);
%Atensor is sparse
Atensor(Atensor_row_num,Atensor_col_num) = 1;
end
Здесь UNIQUE_LENGTH = 223482
и size(network,1)=273209
. Я прогоняю profiler tool
в течение нескольких минут, что было недостаточно для завершения программы, но чтобы достичь устойчивого состояния, когда соотношение времени не слишком сильно изменится. Atensor_row_num = find(NUM_UNI..
равно 45,6% и Atensor_col_num = find(NUM_UNI...
равно 43,4% . Строка с Atensor(Atensor_row_num,Atenso...
, которая присваивает значения матрице sparse
, составляет всего 8,9% . Длина вектора NUM_UNIQUE
довольно велика, поэтому find
является важным аспектом кода; даже важнее, чем редкая матричная манипуляция. Любое улучшение здесь будет значительным. Я не знаю, есть ли более эффективная логическая последовательность для того, чтобы этот алгоритм продолжал работать, вместо того, чтобы использовать простой подход замены find
.