Prototyping med Python-kode før kompilering

stemmer
19

Jeg har vært funderer over å skrive en topp passende biblioteket for en stund. Jeg vet Python ganske godt, og har planer om å gjennomføre alt i Python til å begynne med, men ser for meg at jeg kanskje må re-implementere noen sentrale rutiner i et kompilert språk slutt.

IIRC, en av Python opprinnelige remits var som en prototyping språk, men Python er ganske liberale i å la funksjoner, funktorer, gjenstander som skal sendes til funksjoner og metoder, mens jeg mistenker det samme er ikke tilfelle med si C eller Fortran.

Hva bør jeg vite om å designe funksjoner / klasser som jeg ser for seg nødt til å samhandle i den kompilerte språk? Og hvor mye av disse potensielle problemene behandles av bibliotekene som cTypes, bgen, SWIG , Boost.Python , Cython eller Python SIP ?

For denne spesielle anvendelse tilfellet (en passende bibliotek) forestille jeg som tillater brukere å definere matematiske funksjoner (Guassian, Lorentzian etc.) som Python funksjoner som deretter skal sendes en fortolket av kompilert kode passer bibliotek. Passerer og retur arrays er også avgjørende.

Publisert på 19/08/2008 klokken 12:32
kilden bruker
På andre språk...                            


7 svar

stemmer
35

Til slutt et spørsmål som jeg virkelig kan sette en verdi svar :).

Jeg har undersøkt f2py, boost.python, slurk, cython og pyrex for mitt arbeid (PhD i optiske måleteknikk). Jeg brukte slurk mye, boost.python noen og pyrex og cython mye. Jeg brukte også ctypes. Dette er mitt sammenbrudd:

Disclaimer : Dette er min personlige erfaring. Jeg er ikke involvert i noen av disse prosjektene.

slurk: spiller ikke bra med c ++. Det bør, men navn mangling problemer i å knytte skritt var et stort problem for meg på linux og Mac OS X. Hvis du har C-kode, og ønsker det tilkobles python, er det en god løsning. Jeg pakket GTS for mine behov og nødvendig for å skrive i utgangspunktet en C delt bibliotek som jeg kan koble til. Jeg vil ikke anbefale det.

Ctypes: Jeg skrev en libdc1394 (IEEE Kamera bibliotek) wrapper bruke ctypes og det var en veldig straigtforward opplevelse. Du kan finne koden på https://launchpad.net/pydc1394 . Det er mye arbeid å konvertere hoder til python kode, men så alt fungerer pålitelig. Dette er en god måte hvis du vil grensesnittet en ekstern bibliotek. Ctypes er også i stdlib av python, slik at alle kan bruke koden din med en gang. Dette er også en god måte å leke seg med en ny lib i python raskt. Jeg kan anbefale det til grensesnitt til eksterne libs.

Boost.Python : Veldig hyggelig. Hvis du allerede har C ++ kode du at du vil bruke i python, gå for dette. Det er veldig lett å oversette c ++ klassestrukturer i python klassestrukturer på denne måten. Jeg anbefaler det hvis du har c ++ kode som du trenger i python.

Pyrex / Cython: Bruk Cython, ikke Pyrex. Periode. Cython er mer avansert og mer behagelig å bruke. I dag gjør jeg alt med cython som jeg pleide å gjøre med SWIG eller Ctypes. Det er også den beste måten hvis du har python kode som kjøres for sakte. Prosessen er helt fantastisk: du konvertere python moduler i cython moduler, bygge dem og holde profilering og optimalisering som det fortsatt var pyton (ingen endring av verktøy nødvendig). Du kan deretter bruke like mye (eller lite) C-kode blandet med python-koden. Dette er langt raskere enn å måtte skrive hele deler av programmet i C; du bare skrive den indre sløyfe.

Timing : ctypes har høyest samtalen overhead (~ 700ns), etterfulgt av boost.python (322ns), deretter direkte ved slurk (290ns). Cython har lavest samtale overhead (124ns) og den beste tilbakemeldingen der den tilbringer tid på (cProfile støtte!). Tallene er hentet fra boksen min kalle en triviell funksjon som returnerer et heltall fra en interaktiv skallet; Modulen import overhead er derfor ikke tidsbestemt, er bare funksjonskall overhead. Det er derfor enkleste og mest produktive for å få python kode raskt ved profilering og bruke cython.

Oppsummering : For problemet, kan du bruke Cython;). Jeg håper denne gjennomgangen vil være nyttig for noen mennesker. Jeg vil gjerne svare på eventuelle gjenværende spørsmålet.


Edit : Jeg glemte å nevne: for numeriske formål (det vil si tilkobling til NumPy) bruke Cython; de har støtte for det (fordi de i utgangspunktet utvikle cython for dette formålet). Så dette bør være en annen en for din beslutning.

Svarte 02/11/2009 kl. 13:16
kilden bruker

stemmer
10

Jeg har ikke brukt SWIG eller SIP, men jeg finner skrive Python wrappers med boost.python å være svært kraftig og relativt lett å bruke.

Jeg er ikke klar på hva dine behov er for bestått typer mellom C / C ++ og python, men du kan gjøre det enkelt ved å enten utsette en C ++ type til python, eller ved å bruke en generisk boost :: python :: objekt argument til C ++ API. Du kan også registrere omformere for å automatisk konvertere python typer å C ++ typer og vice versa.

Hvis du planlegger bruk boost.python, den opplæringen er et godt sted å begynne.

Jeg har implementert noe noe som ligner på det du trenger. Jeg har en C ++ funksjon som aksepterer en python funksjon og et bilde som argumenter, og gjelder python funksjon til hver piksel i bildet.

Image* unary(boost::python::object op, Image& im)
{
    Image* out = new Image(im.width(), im.height(), im.channels());
    for(unsigned int i=0; i<im.size(); i++)
    {
        (*out)[i] == extract<float>(op(im[i]));
    }
    return out;
}

I dette tilfelle Bildet er en C ++ gjenstand utsettes for python (et bilde med bildepunkter float), og op er en python definert funksjon (eller egentlig noen python objekt med en __call__ egenskap). Du kan deretter bruke denne funksjonen som følger (forutsatt ensartet ligger i heter bildet som også inneholder bilde og en belastning funksjon):

import image
im = image.load('somefile.tiff')
double_im = image.unary(lambda x: 2.0*x, im)

Som for bruk av matriser med boost, jeg personlig ikke har gjort dette, men jeg vet funksjonalitet for å eksponere matriser til Python bruke boost er tilgjengelig - dette kan være nyttig.

Svarte 26/08/2008 kl. 15:58
kilden bruker

stemmer
6

Den beste måte å planlegge for en eventuell overgang for kompilert kode er å skrive ytelsen sensitive delene som en modul av enkle funksjoner i en funksjonell stil (tilstandsløse og uten bivirkninger), som aksepterer og returnere grunnleggende datatyper.

Dette vil gi en en-til-en mapping fra Python prototype koden til eventuelt kompilert kode, og vil la deg bruke ctypes enkelt og unngå en hel haug med hodepine.

For peak montering, vil du nesten helt sikkert trenger å bruke arrays, som vil komplisere ting litt, men er fortsatt veldig gjennomførbart med ctypes.

Hvis du virkelig ønsker å bruke mer kompliserte datastrukturer, eller endre passerte argumenter, SWIG eller Python standard C-forlengelse grensesnitt vil la deg gjøre hva du vil, men med en viss mengde stress.

For hva du gjør, kan du også ønsker å sjekke ut NumPy , som kan gjøre noe av arbeidet du ønsker å presse til C, samt å tilby litt ekstra hjelp i å flytte data fram og tilbake mellom Python og C .

Svarte 20/08/2008 kl. 01:45
kilden bruker

stemmer
4

f2py (en del av numpy) er et enklere alternativ til SWIG og boost.python for innpakning C / Fortran-nummer-koden knusing.

Svarte 29/09/2008 kl. 22:30
kilden bruker

stemmer
1

I min erfaring, det er to enkle måter å ringe inn C-kode fra Python-kode. Det finnes andre metoder, som alle er mer irriterende og / eller ordrik.

Den første og enkleste er å lage en haug med C-kode som en egen felles bibliotek og deretter ringe funksjoner i det biblioteket du bruker ctypes. Dessverre, passerer noe annet enn grunnleggende datatyper er ikke trivielt.

Den andre enkleste måten er å skrive en Python-modul i C og deretter ringe funksjoner i denne modulen. Du kan sende noe du ønsker å disse C-funksjoner uten å måtte hoppe gjennom noen ringer. Og det er lett å kalle Python funksjoner eller metoder fra disse C-funksjoner, som beskrevet her: https://docs.python.org/extending/extending.html#calling-python-functions-from-c

Jeg har ikke nok erfaring med SWIG å tilby intelligent kommentarer. Og mens det er mulig å gjøre ting som pass tilpassede Python objekter til C-funksjoner gjennom ctypes, eller å definere nye Python klasser i C, disse tingene er irriterende og ordrik, og jeg anbefaler å ta en av de to tilnærmingene er beskrevet ovenfor.

Svarte 19/08/2008 kl. 13:52
kilden bruker

stemmer
0

I tillegg til de ovennevnte verktøy, kan jeg anbefale å bruke Pyrex (for å lage Python tilleggsmoduler) eller Psyco (som JIT kompilator for Python).

Svarte 16/05/2009 kl. 15:08
kilden bruker

stemmer
0

Python er ganske liberalt i å la funksjoner, funktorer, gjenstander som skal sendes til funksjoner og metoder, mens mistenker det samme er ikke tilfelle med si C eller Fortran.

I C kan du ikke passere en funksjon som et argument til en funksjon, men du kan sende en funksjonspeker som er like god funksjon.

Jeg vet ikke hvor mye det ville hjelpe når du prøver å integrere C og Python-kode, men jeg ville bare oppklare en misforståelse.

Svarte 29/09/2008 kl. 22:52
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more