Производительность Julia по сравнению с Python + Numba LLVM / JIT-скомпилированным кодом

Тесты производительности для Julia I, которые я видел до сих пор, например, на http://julialang.org/ , сравнивают Julia с чистым Python или Python + NumPy. В отличие от NumPy, SciPy использует библиотеки BLAS и LAPACK, где мы получаем оптимальную многопоточную реализацию SIMD. Если предположить, что производительность Julia и Python одинакова при вызове функций BLAS и LAPACK (под капотом), как производительность Julia сравнивается с CPython при использовании Numba или NumbaPro для кода, который не вызывает функции BLAS или LAPACK?

Одна вещь, которую я замечаю, это то, что Julia использует LLVM v3.3, а Numba использует llvmlite, который построен на LLVM v3.5. Старая LLVM от Julia предотвращает оптимальную реализацию SIMD на более новых архитектурах, таких как Intel Haswell (инструкции AVX2)?

Меня интересуют сравнения производительности как для кода спагетти, так и для небольших циклов DSP для обработки очень больших векторов. Последнее более эффективно обрабатывается процессором, чем GPU для меня из-за накладных расходов на перемещение данных в и из памяти устройства графического процессора. Меня интересует только производительность на одном процессоре Intel Core i7, поэтому производительность кластера для меня не важна. Особый интерес для меня представляет легкость и успех при создании параллельных реализаций функций DSP.

Вторая часть этого вопроса – сравнение Numba с NumbaPro (игнорирование MKL BLAS). Нужна ли target="parallel" NumbaPro target="parallel" , учитывая новый аргумент nogil для декоратора @jit в Numba?

3 Solutions collect form web for “Производительность Julia по сравнению с Python + Numba LLVM / JIT-скомпилированным кодом”

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

Одна вещь, которую я замечаю, это то, что Julia использует LLVM v3.3, а Numba использует llvmlite, который построен на LLVM v3.5. Старая LLVM от Julia предотвращает оптимальную реализацию SIMD на более новых архитектурах, таких как Intel Haswell (инструкции AVX2)?

[ 2017/01+: приведенная ниже информация больше не относится к текущим выпускам Julia]

Julia отключает avx2 с LLVM 3.3, потому что на Haswell есть некоторые глубокие ошибки.

Julia построена с LLVM 3.3 для текущих выпусков и ночных часов, но вы можете построить с 3.5, 3.6 и обычно svn trunk (если мы еще не обновили некоторые изменения API в данный день, пожалуйста, напишите о проблеме). Чтобы сделать это, установите LLVM_VER=svn (например) в Make.user а затем перейдите к инструкциям сборки.

См. Здесь (раздел 4) для некоторых рецензируемых тестов, которые я лично работал. Сравнение было между Julia и PyPy.

(Сравнение несравнимого всегда является двусторонним мечом.

Нижеследующее представление справедливо полагает, что контрольные показатели кода LLVM / JIT должны сравниваться с некоторыми другими альтернативами LLVM / JIT, если любой производный вывод послужит основой для обоснованных решений.)


Intro: ( numba stuff и [us] результаты немного ниже страницы)

При всем уважении официальный сайт julia-lang представляет собой табличный набор тестов производительности, в котором указаны две категории фактов. Первый, связанный с тем, как был выполнен тест производительности (julia, используя LLVM скомпилированный код-исполнение v / s python, оставаясь выполненным с использованием GIL-интерпретированного кода). Во-вторых, насколько дольше другие языки используют для выполнения одной и той же «контрольной задачи», используя выполнение С-скомпилированного кода как относительную единицу времени = 1.0

Заголовок главы , выше таблицы с результатами, говорит (cit. 🙂

Высокопроизводительный JIT-компилятор
Компилятор Just-in-time (JIT) от Julia LLVM в сочетании с дизайном языка позволяет ему приближаться и часто соответствовать производительности C.

введите описание изображения здесь
Я подумал немного более строго, чтобы сравнить яблоки с яблоками и взял только одну из « контрольных задач », названных pi-sum .

Это было второе худшее время для интерпретируемого python, представленного в 21,99 раза медленнее, чем LLVM / JIT-скомпилированный julia-код или скомпилированная альтернатива.

Итак, начался небольшой эксперимент.

@numba.jit( JulSUM, nogil = True ) :

Давайте начнем сравнивать яблоки с яблоками. Если сообщается, что код julia работает в 22 раза быстрее, давайте сначала измерим простой интерпретируемый запуск кода на питоне.

 >>> def JulSUM(): ... sum = 0. ... j = 0 ... while j < 500: ... j += 1 ... sum = 0. ... k = 0 ... while k < 10000: ... k += 1 ... sum += 1. / ( k * k ) ... return sum ... >>> from zmq import Stopwatch >>> aClk = Stopwatch() >>> aClk.start();_=JulSUM();aClk.stop() 1271963L 1270088L 1279277L 1277371L 1279390L 1274231L 

Итак, ядро pi-sum работает около 1.27x.xxx [us] ~ около 1,27 ~ 1,28 [с]

Учитывая строку таблицы для pi-sum в представлении языка на веб – сайте julia-lang , выполнение julia-кода LLVM / JIT должно выполняться примерно в 22 раза быстрее, т.е. в ~ 57,92 [мс]

 >>> 1274231 / 22 57919 

Итак, давайте преобразуем апельсины в яблоки, используя numba.jit (v24.0)

 >>> import numba >>> JIT_JulSUM = numba.jit( JulSUM ) >>> aClk.start();_=JIT_JulSUM();aClk.stop() 1175206L >>> aClk.start();_=JIT_JulSUM();aClk.stop() 35512L 37193L 37312L 35756L 34710L 

Итак, после того, как JIT-компилятор выполнил свою работу, python numba-LLVM демонстрирует контрольные времена где-то около 34,7 ~ 37,3 [мс]

Можем ли мы пойти дальше?

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

Сначала удалим здесь ненужный GIL-степпинг:

 >>> JIT_NOGIL_JulSUM = numba.jit( JulSUM, nogil = True ) >>> aClk.start();_=JIT_NOGIL_JulSUM();aClk.stop() 85795L >>> aClk.start();_=JIT_NOGIL_JulSUM();aClk.stop() 35526L 35509L 34720L 35906L 35506L 

nogil=True
не приносит исполнение намного дальше,
но все еще бреет несколько [мс] больше, управляя всеми результатами в ~ 35,9 [мс]

 >>> JIT_NOGIL_NOPYTHON_JulSUM = numba.jit( JulSUM, nogil = True, nopython = True ) >>> aClk.start();_=JIT_NOGIL_NOPYTHON_JulSUM();aClk.stop() 84429L >>> aClk.start();_=JIT_NOGIL_NOPYTHON_JulSUM();aClk.stop() 35779L 35753L 35515L 35758L 35585L 35859L 

nopython=True
делает только окончательное прикосновение к полировке
для получения всех результатов последовательно под ~ 35,86 [мс] (против ~ 57,92 [мс] для LLVM / JIT-julia)


Эпилог по обработке DSP:

Ради вопроса OP о дополнительных преимуществах для ускоренной обработки DSP,
можно попробовать и протестировать numba + Intel Python (через Anaconda), где Intel открыла новый горизонт в двоичных файлах, оптимизированный для внутренних процессов IA64-процессора, поэтому выполнение кода может пользоваться дополнительными трюками, связанными с процессорами, на основе знаний Intel об ILP4 , векторизация и предсказание ветвей детализируют свой собственный процессорный дисплей во время выполнения. Стоит проверить, чтобы сравнить это (плюс один может пользоваться своим неразрушающим инструментом анализа кода, интегрированным в VisualStudio, где в реальном времени можно анализировать горячие точки с кодом для обработки кода in-vitro – вещь, которая будет просто инженером DSP , не так ли?

  • PyPy: серьезное снижение производительности при использовании None в списке с целыми числами
  • Разница в производительности между numpy и matlab
  • Где я могу найти сложность времени и пространства встроенных типов последовательностей в Python
  • битовый массив python (исполнитель)
  • Неустойчивая производительность сети python со временем ухудшается?
  • Python Pandas: конвертировать 2,000,000 строк DataFrame в двоичную матрицу (pd.get_dummies ()) без ошибки памяти?
  • Ускорьте скребок
  • Эффективно находить индексы ближайших точек на непрямоугольной 2D сетке
  • Графические плагины процессора для Python
  • Выбор встроенного языка
  • Быстрое вычисление прибыли
  • Python - лучший язык программирования в мире.