Максимальное увеличение производительности с Cython - PullRequest
1 голос
/ 06 марта 2012

Я пытался написать графическое приложение, которое демонстрирует машинное обучение для проекта в университете, и я разрабатывал его на Python.Поскольку Python довольно медленный язык, я искал способы ускорить выполнение во время выполнения и наткнулся на Cython.Я еще не очень знаком с C / C ++, но я пытался статически набирать как можно большую часть своего кода (несмотря на предупреждения о том, что это может снизить удобочитаемость / гибкость; это не моя главная задача на данный момент).

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

ссылка ниже.

Поскольку он все еще находится в стадии разработки, макет невелик, но я выполнил простую группировку функций.

Исходный код можно найти здесь .Ниже приведены наиболее важные части кода.

.

Итерация по памяти данного пэда:

cdef findBestApproximation(int padindex):
    cdef double last_collision_x
    cdef double last_collision_y
    cdef double last_collision_i_angle
    cdef double last_collision_i_speed
    cdef double last_collision_f_angle
    cdef double last_collision_f_speed
    cdef double x_divergence
    cdef double y_divergenve
    cdef double f_angular_divergence
    cdef double divergence

    printData("FINDING APPROXIMATION FOR PAD %s...\n" % padindex)
    pad = Pads.padlist[padindex]
    memory = pad.memory
    ball = Balls.ball
    if not memory:
        approximation = getPadMidpoint(padindex)
        return approximation

    collision_data = getCollisionData()
    (last_collision_x, last_collision_y, last_collision_i_angle,
     last_collision_i_speed, last_collision_f_angle,
     last_collision_f_speed) = collision_data

    best_approx = 0
    strictness_coef = 1.03

    for memory_tuple in memory:
        (x_miss, y_miss, x_collision, y_collision, _, _, f_angle, _) = memory_tuple.getData()
        (divergence, x_divergence, y_divergence, f_angular_divergence) = calculateDivergence(memory_tuple, collision_data)

        divergence = x_divergence + y_divergence + f_angular_divergence

        approximation = (divergence, x_miss, y_miss)

        printData("\n\nPAD: %s" % padindex)
        printData("\nLAST COLLISION (X) = %s, CONSIDERED CASE (X) = %s" % (last_collision_x, x_collision))
        printData("pos_x DIVERGENCE: %s" % x_divergence)

        printData("\nLAST COLLISION (Y) = %s, CONSIDERED CASE (Y) = %s" % (last_collision_y, y_collision))
        printData("pos_y DIVERGENCE: %s" % y_divergence)

        printData("\nLAST COLLISION (fAngle) = %s, CONSIDERED CASE (fAngle) = %s" % (last_collision_f_angle, f_angle))
        printData("FINAL ANGLE DIVERGENCE: %s" % f_angular_divergence)

        printData("\nTOTAL DIVERGENCE: %s\n\n" % divergence)

        if not best_approx:
            best_approx = approximation
        else:
            (least_divergence, _, _) = best_approx 
            if divergence < least_divergence:
                best_approx = approximation

    (_, pos_x, pos_y) = best_approx
    approximation = (pos_x, pos_y)
    return approximation

.

Расчет и атрибуциясчет определенного прошлого события, сохраненного в памяти пэда:

cdef calculateDivergence(memory_tuple, collision_data):
    cdef double pos_x_dif
    cdef double pos_y_dif
    cdef double i_angle_dif
    cdef double i_speed_dif
    cdef double f_angle_dif
    cdef double f_speed_dif

    cdef double max_x_difference
    cdef double max_y_difference
    cdef double max_angular_difference

    cdef double x_divergence
    cdef double y_divergence
    cdef double f_angular_divergence
    cdef double total_divergence

    (last_collision_x, last_collision_y, last_collision_i_angle,
     last_collision_i_speed, last_collision_f_angle,
     last_collision_f_speed) = collision_data

    (x_miss, y_miss, x_collision, y_collision,
     i_angle, i_speed, f_angle, f_speed      ) = memory_tuple.getData()

    pos_x_dif   = abs(x_collision - last_collision_x)
    pos_y_dif   = abs(y_collision - last_collision_y)
    i_angle_dif = getAngleDifference(i_angle, last_collision_i_angle)
    i_speed_dif = abs(i_speed - last_collision_i_speed)
    f_angle_dif = getAngleDifference(f_angle, last_collision_f_angle)
    f_speed_dif = abs(f_speed - last_collision_f_speed)

    max_x_difference       = window_width
    max_y_difference       = window_height
    max_angular_difference = 180

    x_divergence         = 100 * pos_x_dif   / max_x_difference
    y_divergence         = 100 * pos_y_dif   / max_y_difference
    f_angular_divergence = 100 * f_angle_dif / max_angular_difference

    #Apply weights.
    x_divergence         *= WeightData.current_weight
    y_divergence         *= WeightData.current_weight
    f_angular_divergence *= (1 - WeightData.current_weight)

    total_divergence = x_divergence + y_divergence + f_angular_divergence

    divergence_data = (total_divergence, x_divergence, y_divergence, f_angular_divergence)
    return divergence_data

РЕДАКТИРОВАТЬ: Вот результаты профилирования кода.DrawSettingsMenu () - один из худших, но его можно игнорировать (по умолчанию меню настроек не отображается).Любые функции "Initialise ..." также можно игнорировать.

Ответы [ 2 ]

5 голосов
/ 06 марта 2012

Вы должны сначала профилировать свой код и посмотреть, что нужно оптимизировать. Тогда вы должны попытаться оптимизировать алгоритм как можно быстрее. Если вы определили функцию, которая слишком медленная в Python, вы можете попытаться статически напечатать ее, используя Cython, но вы получите лучшую производительность, написав ее на C и вызвав ее из Cython. Но перед оптимизацией убедитесь, что ваш код работает правильно, иначе вы потеряете время.

2 голосов
/ 06 марта 2012

Если вы просто хотите сделать это быстрее, вы можете попробовать альтернативную реализацию Python, такую ​​как PyPy или Unladen Swallow . Если вы используете старую версию Python, вы также можете взглянуть на Psyco .

...