2013-03-27 3 views
2

Я изучаю замену некоторого кода на код кодом python и используя pypy в качестве интерпретатора. В коде много операций с списком/словарем. Поэтому, чтобы получить смутное представление о производительности pypy vs C, я пишу алгоритмы сортировки. Чтобы проверить все мои функции чтения, я написал сортировку пузырьков, как в python, так и в C++. CPython, конечно, сосет 6.468s, pypy пришел в 0.366s и C++ в 0.229s. Затем я вспомнил, что забыл -O3 на C++-коде, и время перешло к 0.042s. Для 32768 набора данных C++ с -O3 всего 2,588 с, а pypy - 19,65 с. Есть ли что-нибудь, что я могу сделать, чтобы ускорить мой код на Python (кроме того, конечно, используя лучший алгоритм сортировки) или как я использую pypy (какой-то флаг или что-то еще)?Оптимизация Pypy (python)

Python код (модуль read_nums опускает, так как это время тривиально: 0.036s на 32768 наборе данных):

import read_nums 
import sys 

nums = read_nums.read_nums(sys.argv[1]) 

done = False 

while not done: 
    done = True 

    for i in range(len(nums)-1): 
     if nums[i] > nums[i+1]: 
      nums[i], nums[i+1] = nums[i+1], nums[i] 
      done = False 

$ time pypy-c2.0 bubble_sort.py test_32768_1.nums 
real 0m20.199s 
user 0m20.189s 
sys  0m0.009s 

C код (функция read_nums снова опускает, так как занимает мало времени: 0.017s):

#include <iostream> 
#include "read_nums.h" 

int main(int argc, char** argv) 
{ 
    std::vector<int> nums; 
    int count, i, tmp; 
    bool done; 

    if(argc < 2) 
    { 
     std::cout << "Usage: " << argv[0] << " filename" << std::endl; 
     return 1; 
    } 

    count = read_nums(argv[1], nums); 

    done = false; 

    while(!done) 
    { 
     done = true; 

     for(i=0; i<count-1; ++i) 
     { 
      if(nums[i] > nums[i+1]) 
      { 
       tmp = nums[i]; 
       nums[i] = nums[i+1]; 
       nums[i+1] = tmp; 
       done = false; 
      } 
     } 
    } 

    for(i=0; i<count; ++i) 
    { 
     std::cout << nums[i] << ", "; 
    } 

    return 0; 
} 

$ time ./bubble_sort test_32768_1.nums > /dev/null 
real 0m2.587s 
user 0m2.586s 
sys  0m0.001s 

PS Некоторые цифры, приведенные в первом абзаце, немного отличаются от цифр, потому что это числа, которые я получил в первый раз.

Дальнейшие усовершенствования:

  • Только что попробовал xrange вместо диапазона и время работы пошел 16.370s.
  • Переведено с кода с done = False до последнего done = False в функции, теперь скорость 8.771-8.834s.
+0

Что произойдет, если вы используете переменную tmp, как в коде c? – Claudiu

+0

W/xrange требуется 19.431s, w/xrange и tmp требуется 19.760s. Не знаю, почему мой xrange просто так сильно регрессировал. – CrazyCasta

+0

Хорошо, xrange no tmp был, по-видимому, выбросом, я запускал его еще 5 раз и менял 16.385s-17.158s. С переменной tmp 5 раз она колебалась от 18.923s-19.444s. – CrazyCasta

ответ

3

Самый подходящий способ ответить на этот вопрос - отметить, что скорость C, CPython и PyPy не зависит от постоянного фактора: это в первую очередь зависит от того, что сделано и как оно написано. Например, если ваш C-код делает наивные вещи, такие как ходовые массивы, когда «эквивалентный» код Python, естественно, использует словари, то любая реализация Python быстрее, чем C, если массивы достаточно длинные. Конечно, это не относится к большинству реальных примеров, но тот же аргумент по-прежнему применяется в меньшей степени. Не существует единого способа определения относительной скорости программы, написанной на C, или перезаписанной на Python и запущенной на CPython или PyPy.

Очевидно, что существуют рекомендации относительно этих относительных скоростей: на небольших алгоритмических примерах вы можете ожидать, что скорость PyPy приближается к скорости «gcc -O0». В вашем примере это «только» на 1,6 раза медленнее. Мы могли бы помочь вам оптимизировать его или даже найти недостатки в PyPy, чтобы получить на 10 или 30% больше скорости. Но это крошечный пример, который не имеет ничего общего с вашей реальной программой. По причинам выше скорость, которую мы получаем здесь, только смутно связана со скоростью, которую вы получите в конце.

Я могу только сказать, что переписывание кода с C на Python по соображениям ясности, особенно когда C слишком запутался для дальнейших разработок, явно выигрывает в конечном счете - даже в случае, когда на в конце вам нужно снова переписать некоторые его части в C. И цель PyPy заключается в том, чтобы уменьшить потребность в этом. Хотя было бы неплохо сказать, что никто больше не нуждается в C, это просто не так. :-)

+0

Две вещи: одна, я хотел бы изучить методы оптимизации PyPy (такие как функции использования вместо того, чтобы делать вещи глобально), два, очевидно, я должен использовать правильную структуру данных в C, но, например, реализация PyPy словарь может быть очень хорошим, и для получения такой же скорости он может принести много усилий на C, и в этом случае PyPy будет иметь преимущество. – CrazyCasta