Подтвердить что ты не робот

Сравнение python с c/fortran

Я написал следующие программы, чтобы сравнить скорость python с c/fortran. Чтобы получить время, используемое программами, я использовал команду "время". Все программы вычисляют квадратный корень из xx + yy + z * z, где x, y, z - поплавки. Я использовал квадрат корня, потому что это одна из самых трудоемких частей в научными вычислениями, в которых я участвую.

Я получил следующие моменты:

fortran  0m29.9s //
c        0m20.7s //
python  30m10.8s

В соответствии с простым тестом я обнаружил, что Python не рекомендуется для научных вычислений. Но, вероятно, мой код очень неэффективен.

Как вы думаете, я мог бы сделать мой код более эффективным только для этого простого теста?

Fortran:

program root_square
implicit none

integer i,j
real x,y,z,r

x=1.0
y=2.0
z=3.0

do j=1,3000
    do i=1,1000000
        r=sqrt(x*x+y*y+z*z)
    enddo
enddo

end program root_square

С

#include "stdio.h"
#include "math.h"

int main (void)
{

float x=1.0,y=2.0,z=3.0,r;
int i,j;

for(j=0; j<3000; j++){
        for(i=0; i<1000000; i++) {
                r=sqrt(x*x+y*y+z*z);
        }
}

return 0;
}

Python:

#!/usr/bin/env python

from math import sqrt

x = 1.0
y = 2.0
z = 3.0

for j in range(1,3001):
  for i in range(1,1000001):
    r = sqrt(x*x+y*y+z*z)
4b9b3361

Ответ 1

Недавно я сделал аналогичный тест с более реалистичным алгоритмом реального мира. Он включает numpy, Matlab, FORTRAN и С# (через ILNumerics). Без определенных оптимизаций numpy, похоже, генерирует гораздо менее эффективный код, чем другие. Конечно, как всегда - это может только предложить общую тенденцию. Вы сможете написать код FORTRAN, который в конце работает медленнее, чем соответствующая реализация numpy. Но в большинстве случаев numpy будет намного медленнее. Здесь (усредненные) результаты моего теста:

kmeans comparison results

Чтобы выполнить такие простые операции с плавающей запятой, как в вашем примере, все сводится к способности компиляторов генерировать "оптимальные" машинные инструкции. Здесь не так важно, сколько задействовано шагов компиляции..NET и numpy используют более одного шага, сначала компилируя в байтовый код, который выполняется на виртуальной машине. Но варианты оптимизации результата в равной степени существуют - теоретически. В практическом плане современные разработчики FORTRAN и C лучше оптимизируют скорость выполнения. В качестве одного из примеров они используют расширения с плавающей запятой (SSE, AVX) и улучшают разворот цикла. numpy (или лучше CPython, который в основном используется numpy), по-видимому, хуже в данный момент. Если вы хотите убедиться, какая структура лучше всего подходит для вашей задачи, вы можете присоединить ее к отладчику и исследовать окончательные машинные инструкции исполняемого файла.

Однако имейте в виду, что в более реалистичном сценарии производительность с плавающей запятой важна только в самом конце большой цепочки оптимизации. Разница часто маскируется гораздо более сильным эффектом: память с полосой пропускания. Как только вы начнете работать с массивами (которые распространены в большинстве научных приложений), вам придется учитывать стоимость управления памятью. Frameworks отклоняются в поддержке автора алгоритма в написании эффективных алгоритмов памяти. По-моему, numpy затрудняет запись эффективных алгоритмов памяти, а затем FORTRAN или C. Но это нелегко на любом из языков. (ILNumerics значительно улучшает это.)

Другим важным моментом является распараллеливание. Поддерживает ли среда поддержку при параллельном выполнении вычислений? И насколько это эффективно? Снова мое личное мнение: ни C, ни FORTRAN, ни numpy не позволяют распараллелить ваши алгоритмы. Но FORTRAN и C по крайней мере дают вам шанс сделать это, даже если иногда требуется использовать специальные компиляторы. Другие структуры (ILNumerics, Matlab) автоматически распараллеливаются.

Если вам нужна "максимальная производительность" для очень маленьких, но дорогостоящих алгоритмов, вам в основном лучше использовать FORTRAN или C. Просто потому, что они в конце генерируют лучший машинный код (в однопроцессорной системе). Однако запись больших алгоритмов в C или FORTRAN и с учетом эффективности памяти и parallelism часто становится громоздкой. Здесь языки более высокого уровня (например, numpy, ILNumerics или Matlab) превосходят языки нижнего уровня. И если все сделано правильно - разница в скорости выполнения часто незначительна. К сожалению, это часто неверно для случая numpy.

Ответ 2

Недостаток тестов.

Если вы хотите использовать арифметику с плавающей запятой, то сначала нужно, чтобы петли ничего не делали (или как можно ближе к нулю). Чтобы избежать оптимизации всего цикла, убедитесь, что он делает что-то вроде перемещения одного байта char из одного массива в другой.

Затем снова запустите вычисление с плавающей запятой и вычтите первое время для получения более точного числа.

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

Ответ 3

Как правило, numpy используется для научных вычислений в python. Вероятно, вы должны проверить эту lib.

Ответ 4

Помните, что вычисление r не зависит от переменных цикла, поэтому оптимизирующий компилятор может вывести вычисление из цикла и просто запустить пустой цикл за запрошенное количество раз; или даже полностью удалить этот цикл и только выполнить вычисление квадратного корня.
Настоящий умный оптимизатор может заметить, что вы ничего не делаете с результатом, поэтому полную программу можно оптимизировать без изменения вывода (т.е. Ничего).

Ответ 5

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

Ответ 6

возможно, вы можете. Существует множество математических библиотек для python, которые, вероятно, могут выполнять задачу, которую вы хотите, немного более эффективно. Поскольку диапазоны python работают совсем не так, как c-циклы, я бы попытался сначала развернуть эти циклы.

Ответ 7

Есть несколько вещей, о которых вы должны знать, прежде чем начинать сравнивать такие тайминги.

  • Как упоминалось в другом ответе, может быть, что компилятор оптимизирует цикл и фактическое значение. Более того, даже если вы печатаете результат, он может просто предварительно вычислить квадратный корень.
  • Вы используете real в Fortran и float в C, поэтому (в зависимости от вашей системы, конечно) компилятор, вероятно, будет использовать вызов библиотеки sqrtf в fortran, тогда как в C вы используете sqrt вместо sqrtf, который вы должны использовать для float.
  • В Python вы должны использовать numpy и scipy, они предоставляют массивы, на которых вы можете выполнять эффективные операции всего массива, избегая цикла в Python.

Ответ 8

для расчетов я могу попробовать haskell или ml...

попробуйте этот код в ML:

fun trip(x,y,z) = if y=z then 0
    else trip(((Math.sqrt((1.0*1.0)+(2.0*2.0)+(3.0*3.0)))*1.0),(y+1),z);
trip(1.0,1,300000000);