2014-12-09 5 views
0

У меня есть этот код Pythonпитон к проблеме производительности C

def transferIntListToIntArray(sourceTuple): 

    myArrayLen = len(sourceTuple) 

    if myArrayLen > 0: 
     targetArray = (c_int * myArrayLen) (*sourceTuple) 
     return targetArray 

    else: 
     return 

def transformIntTupleToIntTab(Input): 

    if Input != None: 
     if type(Input) == int: 
      Input = (Input,) 
     return transferIntListToIntArray(Input); 

    else: 
     return None; 

def myfunc(input): 

    inputTab = transformIntTupleToIntTab(input) 
    mylib.myfuncC.argtype = [type(inputTab)] 
    return mylib.myfuncC(inputTab) 

У меня есть питон файл с тысячами вызовов функции питона MyFunc, как, что, например (MyFunc ((0,1,2,3)) и если я пытаюсь оценить сроки питона кода это питон строка коды имеет важную стоимость:.

targetArray = (c_int * myArrayLen) (*sourceTuple) 

0,1 - 0,2 сек для 10000 вызовов этой функции (Python 2.5.1) Здесь только основные пример, но мой реальный код имеет несколько преобразований кортежа python в int * или double * в C, и мне бы хотелось чтобы знать, как написать более эффективный код Python

пример:

import time 
from ctypes import * 
from cmath import * 

def transferIntListToIntArray(sourceTuple): 
    myArrayLen=len(sourceTuple) 
    if myArrayLen>0: 
     targetArray = (c_int * myArrayLen) (*sourceTuple) 
     return targetArray 
    else: 
     return 


def transformIntTupleToIntTab(Input): 
    if Input != None: 
     if type(Input) == int: 
     Input = (Input,) 
     return transferIntListToIntArray(Input); 
    else: 
     return None; 

def myfunc(iCurve): 
    iCurveTab = transformIntTupleToIntTab(iCurve) 
    return 0 

test = (0,1,2,3,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,55,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5) 

start = time.clock() 

for i in range(100000): 
    myfunc(test) 
print "done, elapsed wall clock time (win32) in seconds: " , time.clock() - start 

сделано, истекшее настенные часы (win32) в секундах: +0,497456968189

же пример в Python 2.7 1,65 секунды (странное)

Python докладываю:

done, elapsed wall clock time (win32) in seconds: 0.582374385947 
     400091 function calls in 0.590 CPU seconds 

    Ordered by: cumulative time 

    ncalls tottime percall cumtime percall filename:lineno(function) 
     1 0.000 0.000 0.590 0.590 <string>:1(<module>) 
     1 0.001 0.001 0.590 0.590 {execfile} 
     1 0.057 0.057 0.589 0.589 tupletest.py:1(<module>) 
    100000 0.035 0.000 0.526 0.000 tupletest.py:22(myfunc) 
    100000 0.068 0.000 0.491 0.000 tupletest.py:14(transformIntTupleToIntTab) 
    100000 0.417 0.000 0.423 0.000 tupletest.py:5(transferIntListToIntArray) 
    100003 0.006 0.000 0.006 0.000 {len} 
     1 0.004 0.004 0.005 0.005 __init__.py:4(<module>) 
     1 0.002 0.002 0.002 0.002 {range} 
     1 0.000 0.000 0.000 0.000 _endian.py:4(<module>) 
     4 0.000 0.000 0.000 0.000 __init__.py:83(CFUNCTYPE) 
     2 0.000 0.000 0.000 0.000 __init__.py:211(POINTER) 
     1 0.000 0.000 0.000 0.000 __init__.py:291(CDLL) 
     1 0.000 0.000 0.000 0.000 __init__.py:335(PyDLL) 
     1 0.000 0.000 0.000 0.000 __init__.py:441(PYFUNCTYPE) 
     1 0.000 0.000 0.000 0.000 __init__.py:346(WinDLL) 
     4 0.000 0.000 0.000 0.000 struct.py:43(calcsize) 
     1 0.000 0.000 0.000 0.000 __init__.py:322(__getattr__) 
     1 0.000 0.000 0.000 0.000 __init__.py:370(OleDLL) 
     1 0.000 0.000 0.000 0.000 __init__.py:384(__getattr__) 
     1 0.000 0.000 0.000 0.000 __init__.py:329(__getitem__) 
     2 0.000 0.000 0.000 0.000 __init__.py:309(__init__) 
     1 0.000 0.000 0.000 0.000 {_ctypes.LoadLibrary} 
     3 0.000 0.000 0.000 0.000 struct.py:35(_compile) 
     1 0.000 0.000 0.000 0.000 {_ctypes.set_conversion_mode} 
     4 0.000 0.000 0.000 0.000 __init__.py:381(__init__) 
     2 0.000 0.000 0.000 0.000 {time.clock} 
     18 0.000 0.000 0.000 0.000 {_ctypes.sizeof} 
     3 0.000 0.000 0.000 0.000 __init__.py:101(CFunctionType) 
     1 0.000 0.000 0.000 0.000 {isinstance} 
     1 0.000 0.000 0.000 0.000 __init__.py:442(CFunctionType) 
     1 0.000 0.000 0.000 0.000 __init__.py:144(c_short) 
     1 0.000 0.000 0.000 0.000 __init__.py:380(LibraryLoader) 
     2 0.000 0.000 0.000 0.000 {setattr} 
     1 0.000 0.000 0.000 0.000 _endian.py:22(_swapped_meta) 
     1 0.000 0.000 0.000 0.000 __init__.py:340(_FuncPtr) 
     1 0.000 0.000 0.000 0.000 __init__.py:136(py_object) 
     1 0.000 0.000 0.000 0.000 {method 'startswith' of 'str' objects} 
     1 0.000 0.000 0.000 0.000 _endian.py:45(BigEndianStructure) 
     1 0.000 0.000 0.000 0.000 __init__.py:181(c_ulonglong) 
     1 0.000 0.000 0.000 0.000 __init__.py:167(c_float) 
     1 0.000 0.000 0.000 0.000 __init__.py:147(c_ushort) 
     1 0.000 0.000 0.000 0.000 __init__.py:178(c_longlong) 
     1 0.000 0.000 0.000 0.000 __init__.py:197(c_char) 
     1 0.000 0.000 0.000 0.000 __init__.py:305(_FuncPtr) 
     1 0.000 0.000 0.000 0.000 __init__.py:376(_FuncPtr) 
     1 0.000 0.000 0.000 0.000 __init__.py:153(c_ulong) 
     1 0.000 0.000 0.000 0.000 __init__.py:243(c_wchar) 
     1 0.000 0.000 0.000 0.000 __init__.py:204(c_void_p) 
     1 0.000 0.000 0.000 0.000 __init__.py:187(c_ubyte) 
     1 0.000 0.000 0.000 0.000 __init__.py:201(c_char_p) 
     1 0.000 0.000 0.000 0.000 __init__.py:240(c_wchar_p) 
     1 0.000 0.000 0.000 0.000 __init__.py:150(c_long) 
     1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} 
     1 0.000 0.000 0.000 0.000 __init__.py:193(c_byte) 
     1 0.000 0.000 0.000 0.000 __init__.py:170(c_double) 
     1 0.000 0.000 0.000 0.000 __init__.py:357(HRESULT) 
     1 0.000 0.000 0.000 0.000 __init__.py:350(_FuncPtr) 

Пример с 2 вкладки: (цель здесь заключается в преобразовании iCurve1 и iCurve2 в Int * для функции C) по телефону mylibC.myfunC(iCurveTab1 , iCurveTab2) и код C является myfuncC(int *iCurveTab1, int *iCurveTab2)

import time 
from ctypes import * 
from cmath import * 

def transferIntListToIntArray(sourceTuple): 
    myArrayLen=len(sourceTuple) 
    if myArrayLen>0: 
     targetArray = (c_int * myArrayLen) (*sourceTuple) 
     return targetArray 
    else: 
     return 


def transformIntTupleToIntTab(Input): 
    if Input != None: 
     if type(Input) == int: 
     Input = (Input,) 
     return transferIntListToIntArray(Input); 
    else: 
     return None; 

def myfunc(iCurve1, iCurve2): 
    iCurveTab1 = transformIntTupleToIntTab(iCurve1) 
    iCurveTab2 = transformIntTupleToIntTab(iCurve2) 
    return 0 

test = (0,1,2,3,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,55,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5) 

start = time.clock() 

for i in range(100000): 
    myfunc(test, test) 
print "done, elapsed wall clock time (win32) in seconds: " , time.clock() - start 

В Python 2.5: сделано, часы истекшее стены (win32) в секундах : 0,96631573455

в Python 2.7: сделан, истекшее время настенных часов (win32) в секундах: 3,25996918937

  1. как я могу улучшить этот питон код? (Хорошая предыдущая идея deets не работает, потому что iCurveTab1 и iCurveTab2 будет использовать тот же указатель C
  2. кажется, есть регресс в Python 2.7 из-за этого кода

Мой реальный код с с интерфейсом кода Python mytest.py

import time 
    from ctypes import * 
    from cmath import * 

    def transferIntListToIntArray(sourceTuple): 
     myArrayLen=len(sourceTuple) 
     if myArrayLen>0: 
      targetArray = (c_int * myArrayLen) (*sourceTuple) 
      return targetArray 
     else: 
      return 


    def transformIntTupleToIntTab(Input): 
     if Input != None: 
      if type(Input) == int: 
      Input = (Input,) 
      return transferIntListToIntArray(Input); 
     else: 
      return None; 

    def myfunc(iCurve1, iCurve2): 
     iCurveTab1 = transformIntTupleToIntTab(iCurve1) 
     iCurveTab2 = transformIntTupleToIntTab(iCurve2) 
     return mylibC.myfuncC(len(iCurveTab1), len(iCurveTab2), iCurveTab1, iCurveTab2) 

C Код

void myfuncC(int ilen1, int ilen2, int *piCurve1, int *piCurve2) 
{ 

    return; 
} 

если iCurveTab1 и iCurveTab2 один и тот же кэш piCur ve1 = piCurve2 и это является проблемой, поскольку значения стираются

Мой питон, который исполняется:

from mytest * 
myfunc((1,2,3,4),(7,8,9,10,11)) 

Благодарности

+2

Некоторые nitpicks: Вам не нужно semicola, где вы используете их, проверяя Нискол идиоматически сделано с «является» -оператором (Foo является None) – deets

ответ

1

Не воссоздавать массивы, кажется, сохранить совсем немного времени для меня.

import time 
from ctypes import * 
from cmath import * 


iCurve1Cache = {} 
iCurve2Cache = {} 

def transferIntListToIntArray(sourceTuple, array_type_cache): 
    myArrayLen=len(sourceTuple) 
    if myArrayLen>0: 
     if myArrayLen not in array_type_cache: 
      array_type_cache[myArrayLen] = (c_int * myArrayLen)() 

     targetArray = array_type_cache[myArrayLen] 
     targetArray[:] = sourceTuple 
     return targetArray 
    else: 
     return 


def transformIntTupleToIntTab(Input): 
    if Input != None: 
     if type(Input) == int: 
      Input = (Input,) 
     return transferIntListToIntArray(Input); 
    else: 
     return None; 

def myfunc(iCurve1, iCurve2): 
    iCurveTab1 = transformIntTupleToIntTab(iCurve1, iCurve1Cache) 
    iCurveTab2 = transformIntTupleToIntTab(iCurve2, iCurve2Cache) 
    return 0 

test = (0,1,2,3,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,55,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5) 

start = time.clock() 

for i in range(100000): 
    myfunc(test) 
print "done, elapsed wall clock time (win32) in seconds: " , time.clock() - start 

На моем mac это сокращает время с 1.267731 секунды до 0,36 секунды.

Если вам нужна дополнительная оптимизация, нам нужна дополнительная информация.

+0

Благодаря мой результат на Windows 7 Python 2.5 то же время 0,45 Python 2.7 до 1.7 после 0.42 Ваша оптимизация работает с python 2.7, но python 2.7 уже что-то странное – parisjohn

+0

Какую информацию вы хотите? – parisjohn

+0

Ваш оптимизатор не работает, если в myfunc у меня есть два разных вызова transformIntTupleToIntTab, указатели на cpu будут одинаковыми, потому что он использует тот же массив в кеше – parisjohn

 Смежные вопросы

  • Нет связанных вопросов^_^