Я недавно провел аналогичный тест с более реалистичным алгоритмом реального мира. Он включает в себя Numpy, Matlab, FORTRAN и C # (через ILNumerics ). Без определенных оптимизаций Numpy генерирует гораздо менее эффективный код, чем другие. Конечно, как всегда, это может указывать только на общую тенденцию. Вы сможете написать код на Фортране, который в конце будет работать медленнее, чем соответствующая реализация. Но в большинстве случаев NumPy будет гораздо медленнее. Вот (усредненные) результаты моего теста:
Чтобы рассчитать время таких простых операций с плавающей запятой, как в вашем примере, все сводится к способности компиляторов генерировать «оптимальные» машинные инструкции. Здесь не так важно, сколько этапов компиляции задействовано. .NET и numpy используют более одного шага, сначала компилируя в байтовый код, который выполняется на виртуальной машине. Но варианты для оптимизации результата в равной степени существуют - в теории. На практике современные компиляторы FORTRAN и C лучше оптимизируют скорость выполнения. В качестве одного примера они используют расширения с плавающей запятой (SSE, AVX) и лучше развертывают циклы. Numpy (или лучше CPython, который в основном используется Numpy), кажется, работает хуже в этой точке. Если вы хотите убедиться, какая среда лучше всего подходит для вашей задачи, вы можете подключиться к отладчику и исследовать окончательные машинные инструкции исполняемого файла.
Однако имейте в виду, что в более реалистичном сценарии производительность с плавающей запятой важна только в самом конце большой цепочки оптимизации. Различие часто маскируется гораздо более сильным эффектом: пропускной способностью памяти. Как только вы начнете обрабатывать массивы (что часто встречается в большинстве научных приложений), вам придется учитывать стоимость управления памятью. Структуры отклоняются в поддержке автора алгоритма в написании эффективных алгоритмов памяти. По моему мнению, numpy усложняет написание алгоритмов, эффективно использующих память, чем FORTRAN или C. Но это нелегко для любого из этих языков. (ILNumerics значительно улучшает это.)
Другим важным моментом является распараллеливание. Поддерживает ли фреймворк выполнение ваших вычислений параллельно? И насколько это эффективно? Опять же мое личное мнение: ни C, ни FORTRAN, ни Numpy не позволяют легко распараллелить ваши алгоритмы. Но FORTRAN и C по крайней мере дают вам возможность сделать это, даже если иногда требуется использование специальных компиляторов. Другие фреймворки (ILNumerics, Matlab) распараллеливаются автоматически.
Если вам нужна «пиковая производительность» для очень маленьких, но дорогостоящих алгоритмов, вам в основном будет лучше использовать FORTRAN или C. Только потому, что они в конце генерируют лучший машинный код (в однопроцессорной системе). Однако написание более крупных алгоритмов на C или FORTRAN и с учетом эффективности использования памяти, параллелизма и часто становится громоздким. Здесь языки более высокого уровня (такие как numpy, ILNumerics или Matlab) превосходят языки более низкого уровня. И если все сделано правильно - разница в скорости выполнения часто ничтожна. К сожалению, это часто не так в случае с NumPy.