Производительность создания индекса

В попытке выбрать, какой метод индексирования рекомендуется рекомендовать, я попытался измерить производительность. Однако измерения меня смутили. Я выполнял это несколько раз в разных порядках, но измерения оставались неизменными. Вот как я измерил производительность:

for N = [10000 15000 100000 150000]
    x =  round(rand(N,1)*5)-2;
    idx1 = x~=0;
    idx2 = abs(x)>0;

    tic
    for t = 1:5000
        idx1 = x~=0;
    end
    toc

    tic
    for t = 1:5000
        idx2 = abs(x)>0;
    end
    toc
end

И это результат:

Elapsed time is 0.203504 seconds.
Elapsed time is 0.230439 seconds.

Elapsed time is 0.319840 seconds.
Elapsed time is 0.352562 seconds.

Elapsed time is 2.118108 seconds. % This is the strange part
Elapsed time is 0.434818 seconds.

Elapsed time is 0.508882 seconds.
Elapsed time is 0.550144 seconds.

Я проверил, и для значений около 100000 это также происходит, даже при 50000 происходят странные измерения.

Итак, мой вопрос: кто-нибудь еще испытывает это для определенного диапазона, и что вызывает это? (Это ошибка?)

Ответ 1

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

Как и ваша, моя конфигурация (OSX 10.8.4, R2012a с настройками по умолчанию) занимает больше времени, чтобы вычислить idx1 = x~=0 для x (элементы 10e5), чем x (элементы 11e5). См. Левую панель фигуры, на которой измеряется время обработки (ось y) для разных размеров вектора (ось x). Вы увидите более низкое время для N > 103000. На этой панели я также показал количество ядер, которые были активны во время вычисления. Вы увидите, что для одноядерной конфигурации нет снижения. Это означает, что Matlab не оптимизирует выполнение ~=, когда активен 1 ядро ​​(без возможности параллелизации). Matlab допускает некоторые подпрограммы оптимизации, когда выполняются два условия: несколько ядер и вектор достаточного размера.

На правой панели отображаются результаты, когда feature('accel','on'/off') отключен (doc). Здесь активна только одно ядро ​​(одноядерные и четырехъядерные идентичны), и поэтому оптимизация невозможна.

Наконец, функция I, используемая для активации/деактивации ядер, составляет maxNumCompThreads. Согласно Loren Shure, maxNumCompThreads управляет как JIT, так и BLAS. Поскольку feature('JIT','on'/'off') не играет роли в производительности, BLAS - последний оставшийся вариант.

Я оставлю последнее предложение Лорену: "Главное сообщение здесь в том, что вам вообще не нужно вообще использовать эту функцию [maxNumCompThreads]! Почему? Потому что мы хотели бы, чтобы MATLAB делал наилучшую работу для вы". enter image description here

accel = {'on';'off'};
figure('Color','w');
N = 100000:1000:105000;

for ind_accel = 2:-1:1
    eval(['feature(''accel'',''' accel{ind_accel} ''')']);
    tElapsed = zeros(4,length(N));
    for ind_core = 1:4
        maxNumCompThreads(ind_core);
        n_core = maxNumCompThreads;
        for ii = 1:length(N)
            fprintf('core asked: %d(true:%d) - N:%d\n',ind_core,n_core, ii);
            x =  round(rand(N(ii),1)*5)-2;
            idx1 = x~=0;
            tStart = tic;
            for t = 1:5000
                idx1 = x~=0;
            end
            tElapsed(ind_core,ii) = toc(tStart);
        end
    end
    h2 = subplot(1,2,ind_accel);
    plot(N, tElapsed,'-o','MarkerSize',10);
    legend({('1':'4')'});
    xlabel('Vector size','FontSize',14);
    ylabel('Processing time','FontSize',14);
    set(gca,'FontSize',14,'YLim',[0.2 0.7]);
    title(['accel ' accel{ind_accel}]);
end

Ответ 2

Я думаю, что это как-то связано с JIT (результаты ниже используются в 2011b). В зависимости от системы, версии Matlab, размера переменных и того, что находится в цикле (-ах), не всегда быстрее использовать JIT. Это связано с эффектом "разминки", когда иногда, если вы запускаете m файл более одного раза в сеансе, он становится быстрее после первого запуска, так как ускоритель должен только один раз компилировать некоторые части кода.

JIT on (функция ускорения включена)

Elapsed time is 0.176765 seconds.
Elapsed time is 0.185301 seconds.

Elapsed time is 0.252631 seconds.
Elapsed time is 0.284415 seconds.

Elapsed time is 1.782446 seconds.
Elapsed time is 0.693508 seconds.

Elapsed time is 0.855005 seconds.
Elapsed time is 1.004955 seconds.

JIT выключено (функция ускорена)

Elapsed time is 0.143924 seconds.
Elapsed time is 0.184360 seconds.

Elapsed time is 0.206405 seconds.
Elapsed time is 0.306424 seconds.

Elapsed time is 1.416654 seconds.
Elapsed time is 2.718846 seconds.

Elapsed time is 2.110420 seconds.
Elapsed time is 4.027782 seconds.

ETA, интересно посмотреть, что произойдет, если вы используете целые числа вместо двухлокальных:

JIT on, тот же код, но преобразованный x с помощью int8

Elapsed time is 0.202201 seconds.
Elapsed time is 0.192103 seconds.

Elapsed time is 0.294974 seconds.
Elapsed time is 0.296191 seconds.

Elapsed time is 2.001245 seconds.
Elapsed time is 2.038713 seconds.

Elapsed time is 0.870500 seconds.
Elapsed time is 0.898301 seconds.

JIT выключен, используя int8

Elapsed time is 0.198611 seconds.
Elapsed time is 0.187589 seconds.

Elapsed time is 0.282775 seconds.
Elapsed time is 0.282938 seconds.

Elapsed time is 1.837561 seconds.
Elapsed time is 1.846766 seconds.

Elapsed time is 2.746034 seconds.
Elapsed time is 2.760067 seconds.