W programie MATLAB, mam for loop
, który ma wiele interakcji przejść i wypełnić matrycę sparse
. Program jest bardzo powolny i chciałbym go zoptymalizować, aby zakończyć go niedługo. W dwóch wierszach używam polecenia find
, a edytor MATLAB ostrzega mnie, że użycie logical indexing
zamiast find
poprawi wydajność. Mój kod jest bardzo podobny do tego przedstawionego nowicjuszowi mathworks, mathworks newsreader recommendation, gdzie znajduje się wektor wartości i wektor unikalnej wartości z niego wygenerowanej. Używa find
do uzyskania indeksu w unikatowych wartościach (do aktualizacji wartości w macierzy). Mówiąc krótko, kod podany jest:Jak zastąpić polecenia `find` za pomocą` indeksowania logicznego` (MATLAB), aby wyszukać wartości wartości wektorowych o unikalnych wartościach?
positions = find(X0_outputs == unique_outputs(j,1));
% should read
positions = X0_outputs == unique_outputs(j,1);
Jednak ostatnia linia nie jest indeksem, ale wektorem zer i jedynek. Mam przykład ilustrujący, zrób zestaw indeksów; tt=round(rand(1,6)*10)
:
tt = 3 7 1 7 1 7
Stwórz unikalny wektor;
ttUNI = 1 3 7
Wykorzystanie znaleźć, aby uzyskać indeks pozycję wartości w zbiorze unikalnych wartości; find(ttUNI(:) == tt(1))
ans = 2
Porównaj z wykorzystaniem logicznego indeksowania; (ttUNI(:) == tt(1))
ans =
0
1
0
o wartości 2
jest dużo bardziej przydatne niż tego wektora binarnego kiedy muszę zaktualizować indeksy dla macierzy. Dla mojej matrycy mogę powiedzieć mat(find(ttUNI(:) == tt(1)), 4)
i to działa. Podczas gdy użycie (ttUNI(:) == tt(1))
wymaga przetwarzania.
Czy istnieje schludny i skuteczny sposób robienia tego, co jest potrzebne? A może nie jest to konieczne w takich okolicznościach?
UPDATE: będę zawierać kod tutaj jako zalecana przez użytkownika: @Jonas dać lepszy wgląd w problem, który mam i zgłoś niektóre z wyników narzędzia Profiler jest.
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
Tutaj UNIQUE_LENGTH = 223482
i size(network,1)=273209
. Przez kilka minut robiłem randkę, co nie było wystarczającym czasem na zakończenie programu, ale na osiągnięcie stanu ustalonego, gdy stosunek czasów nie zmieniłby się zbytnio. Atensor_row_num = find(NUM_UNI..
jest 45,6% i Atensor_col_num = find(NUM_UNI...
jest 43,4%. Linia z Atensor(Atensor_row_num,Atenso...
, która przydziela wartości do macierzy sparse
, jest tylko 8.9%. Długość wektora NUM_UNIQUE
jest dość duża, więc find
jest ważnym aspektem kodu; jeszcze ważniejsze niż rzadka manipulacja matrycą. Każda poprawa tutaj byłaby znacząca. Nie wiem, czy istnieje bardziej wydajny postęp logiczny dla tego algorytmu, aby postępować, jak również zamiast prostego podejścia do zastępowania find
.
Chciałem tylko dodać, że o ile mogę powiedzieć, że ostrzeżenie wiadomość jest w mniejszym lub większym stopniu wywoływana przez każde wezwanie do znalezienia. Niedawno natknąłem się na sytuację, w której indeksowana logicznie wersja była znacznie wolniejsza niż ta, którą nazwałem find(). Jeśli jest to sytuacja krytyczna w czasie, spróbowałbym obu sposobów. –