Почему Юля медленнее MATLAB? - PullRequest
       21

Почему Юля медленнее MATLAB?

1 голос
/ 07 августа 2020

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

MATLAB:

tic

aa = 0;

for loop =1:1e6

       aa = aa+loop;

end

toc

Затраченное время составляет 0,004628 секунды.

Julia:

function sum_test(a)

    for i = 1:1e6
        a = a + i
    end

    return a
end

Затраченное время 0,093886155 s: 93 миллисекунды.

Я также написал функцию в Julia, чтобы избежать использования глобальных переменных, которые улучшили производительность, но по-прежнему значительно медленнее, чем MATLAB. Может кто-нибудь помочь мне разобраться в этом, пожалуйста?

1 Ответ

8 голосов
/ 07 августа 2020

Невозможно сказать, не видя, как вы синхронизируете свой код Julia. Однако наиболее вероятное объяснение заключается в том, что вы рассчитываете время как компиляции, так и времени выполнения. Компиляторы Julia и MatLab ведут себя по-разному. Когда вы пишете новую функцию в Julia, она компилируется при первом использовании. Следовательно, первое его выполнение будет довольно медленным, но все последующие вызовы будут быстрыми. Чтобы обойти это, если вы тестируете Джулию, рекомендуется использовать пакет BenchmarkTools. На моей (не особо специальной) машине:

function sum_test(a)
    for i = 1:1e6
        a = a + i
    end
    return a
end
using BenchmarkTools
@btime sum_test(1)

дает следующий результат:

julia> @btime sum_test(1)
  2.135 ms (0 allocations: 0 bytes)

, то есть примерно 2 миллисекунды, что примерно в два раза быстрее, чем ваш запуск MatLab.

Но можем ли мы сделать лучше? Конечно, можем. MatLab имеет тенденцию обрабатывать все числа, как будто они являются числами с плавающей запятой двойной точности, и поэтому при кодировании в MatLab не нужно слишком много думать о типе своих чисел. В Юлии это не так. В этом примере вы указали верхнюю границу l oop как 1e6. Обратите внимание:

julia> typeof(1e6)
Float64

Ага! Вероятно, вы не предполагали, что ваша переменная l oop должна быть Float64, а скорее хотела, чтобы она была целым числом. Что же произойдет, если мы его изменим? Попробуйте запустить это:

function sum_test(a)
    for i = 1:1000000
        a = a + i
    end
    return a
end
using BenchmarkTools
@btime sum_test(1)

Теперь это выводит:

julia> @btime sum_test(1)
  1.208 ns (0 allocations: 0 bytes)

Да, вы правильно прочитали. Это заняло 1,2 наносекунды, что примерно на 6 порядков быстрее, чем у MatLab.

Так что же происходит? В случае, когда верхняя граница l oop является целым числом, компилятор Julia достаточно умен, чтобы понять, что на самом деле ему не нужно запускать l oop для правильной обработки результата. Из-за характера выполняемого алгоритма ответ может быть определен с помощью одной формулы, которую компилятор сделал за вас. Другими словами, компилятор Julia полностью оптимизировал l oop!

...