Разница в скорости в Python, скомпилированном с помощью MS C, по сравнению с MinGW

На моей машине с Windows 7 я использую две реализации CPython:

1) дистрибутив WinPython, скомпилированный с помощью MSC v.1500 64bit.

2) MinGW-сборки, который скомпилирован с MinGW/GCC 4.9.1 64bit

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

import pickle, cPickle, random
from time import clock

def timeit(mdl, d, num=100, bestof=10):
    times = []
    for _ in range(bestof):
        start = clock()
        for _ in range(num):
            mdl.loads(mdl.dumps(d))
        times.append(clock() - start)
    return min(times)

def gen_dict(entries=100, keylength=5):
    formatstr = "{:0%dx}" % keylength
    d = {}
    for _ in range(entries):
        rn = random.randrange(16**keylength) # 'keylength'-digit hex number
        # format into string of length 5 as key, decimal value as value
        d[formatstr.format(rn)] = rn
    return d

def main(entries=100, keylength=5, num=100, bestof=10):
    print "Dict size: %d entries, keylength: %d" % (entries, keylength)
    print ("Test is %d times pack/unpack. "
           "Take best time out of %d runs\n" % (num, bestof))
    d = gen_dict(entries, keylength)
    for mdl in [pickle, cPickle]:
        print "%s: %f s" % (mdl.__name__, timeit(mdl, d, num, bestof))

if __name__ == "__main__":
    main()

MSC CPython дал мне

Dict size: 100 entries, keylength: 5
Test is 100 times pack/unpack. Take best time out of 10 runs

pickle: 0.107798 s
cPickle: 0.011802 s

и MinGW/GCC CPython дал мне

Dict size: 100 entries, keylength: 5
Test is 100 times pack/unpack. Take best time out of 10 runs

pickle: 0.103065 s
cPickle: 0.075507 s

Таким образом, модуль cPickle (расширение стандартной библиотеки C для Python) работает на MinGW в 6,4 раза медленнее, чем на MSC.
Я не проводил дальнейших исследований (т.е. не тестировал больше расширений C), но я очень удивлен.
Так ли это? этого следовало ожидать?
Будут ли другие расширения C работать медленнее в цепочке инструментов Python/MinGW?


person Pybe    schedule 17.09.2014    source источник


Ответы (1)


Я использовал MSYS2 и цепочку инструментов MinGW-w64 для компиляции большого расширения, привязанного к процессору. Он не работал необычно медленно; Я на самом деле думаю, что он работает быстрее, чем MSC. Одна из возможных причин медленных расширений: Mingw32CCompiler класс, содержащийся в файле, cygwincompiler.py указал -O оптимизацию. Я изменил это на -O2, и производительность улучшилась.

Я использую расширение со стандартным CPython, распространяемым с python.org.

Обновить

Я попробовал ваш образец программы на MSYS2. Доступны две версии Python 2.7: одна является частью дистрибутива MSYS2, а другая — частью цепочки инструментов MinGW-w64. Версия, включенная в MSYS2, не имеет проблем с производительностью, в то время как версия, включенная в MinGW-w64, демонстрирует проблемы с производительностью cPickle. Поскольку версия MSYS2 компилируется GCC, включенным в MinGW-w64, я считаю, что замедление связано с конкретными параметрами, используемыми при компиляции версии MinGW. Я не смотрел исходный код для обеих версий, чтобы увидеть, в чем причина разницы.

Что касается требования использовать ту же версию компилятора для расширения, что и интерпретатор Python, то ответ "Это зависит от...". Проблема возникает из-за незначительных различий между библиотекой времени выполнения C, используемой каждой основной версией MSC. IIRC, одно из отличий может нарушить передачу дескрипторов файлов между Python и расширением. Если вы не используете какие-либо вызовы, основанные на различиях, вы можете смешивать версии компиляторов. Поскольку не существует ни окончательного списка различий, ни способа запретить расширению выполнять эти разные вызовы, единственный гарантированный ответ — не смешивать версии. Мое расширение не использует (я думаю) какие-либо другие вызовы среды выполнения C. Он использует только Python C-API для всех операций ввода-вывода и управления памятью. Я успешно смешивал версии компиляторов при тестировании, но предпочитаю этого не делать.

Я все еще экспериментирую с подходом MSYS2/MinGW-w64 для создания моего расширения и использования его с скомпилированной MSC версией CPython. Похоже, он работает, и он работает так, как ожидалось.

person casevh    schedule 18.09.2014
comment
Версии с python.org, насколько я знаю, скомпилированы с помощью MSC. Значит, вы не используете версию CPython, скомпилированную с помощью MinGW, верно? Это не будет противоречить вышеприведенным результатам. Всегда ли проблематично использовать разные компиляторы для Python и для расширений? - person Pybe; 19.09.2014
comment
@Pybe Я расширил свой ответ. - person casevh; 19.09.2014
comment
Ты прав! Версия MSYS2 доработана. Спасибо, что указали мне там. - person Pybe; 20.09.2014