Мы все более или менее привержены использованию языков высокого уровня, но всегда есть фоновое беспокойство, что они могут быть недостаточно быстрыми для некоторых задач. Интересный набор тестов показывает, как использовать Python для вычисления crunch.
Эталоном в этом случае является очень простое, но трудоемкое вычисление-множество Мандельброта. Что действительно интересно, так это не столько задача, подумайте о проблеме общего хруста чисел, сколько различные технологии, которые Жан Франсуа Пьюже, инженер-программист IBM, использовал для ее вычисления.
Начиная с «наивного» Python, тройные вложенные циклы сканируют x, сканируют y и повторяют функцию, чтобы получить базовую линию. Это примерно в 70 раз медленнее, чем код на языке Си.
Наивный код использует списки для хранения результатов, поэтому следующая «оптимизация» изменяет списки на массивы Numpy и явные циклы. Он оказывается медленнее, примерно в 110 раз медленнее, чем C, хотя структура данных, массив, проще, и на других языках можно было бы ожидать, что он будет быстрее.
Если вы хотите, чтобы массивы были быстрее в Python, вам нужно переключиться на компилятор, который может использовать преимущества его фиксированной регулярной компоновки. Numba, JIT-компилятор и Cython превратились во времена, сравнимые с простым кодом на языке Си.
Таким образом, на данный момент кажется, что проблема не в языке, а в том, как он реализован. Если у вас достаточно хороший компилятор, то язык высокого уровня может быть таким же быстрым, как C, который можно рассматривать как низкоуровневый, независимый от машины ассемблер.
Следующий вопрос заключается в том, может ли язык высокого уровня ускорить процесс, используя расширенные абстракции, которые используют преимущества аппаратного обеспечения. Например, может ли векторизация использовать преимущества операций типа SIMD, чтобы сделать работу быстрее, чем чисто последовательная программа на языке Си?
Если векторизация обеспечивается Numpy, ответ заключается в том, что она лучше, но не намного, примерно в 3 раза медленнее, чем последовательная C. Однако это лучше, чем невекторизованный Numpy и наивный Python. Векторизация Numba дает аналогичную производительность в 2 раза медленнее, чем последовательная C.
Глядя за пределы основного языка, TensorFlow, пакет искусственного интеллекта Google, можно использовать для векторизации вычислений. Используя только процессор, TensorFlow работает примерно с той же скоростью, что и векторизованный Numpy, то есть примерно в 3 раза медленнее.
Хорошо, а как насчет использования графического процессора?
PyOpenCL и PyCUDA предоставляют довольно прямой доступ к графическому процессору и, как и следовало ожидать, выполняют более или менее то же самое примерно в 15 раз быстрее, чем последовательная программа на языке Си. Если вы хотите использовать графический процессор и сохранить подход более высокого уровня, вы можете использовать Numba Guvectorize, который требует только, чтобы вы поместили target=’parallel’ в свой код. Это работает примерно в 3,5 раза быстрее, чем последовательная программа на языке Си.
Полная таблица результатов:
Итак, вот оно.
Чистый Python медленен по сравнению с простым C, и чтобы сделать его быстрее, вам нужно его скомпилировать.
Если вы хотите работать быстрее, чем C, вам нужно перейти с процессора на графический процессор, и это можно сделать, используя подход высокого уровня.
Это в значительной степени обзор результатов и процедур, поэтому перейдите и взгляните на полный пост в блоге для получения остальной информации.