2011-11-09 13 views
14

Ho alcune funzioni scritte in C per un progetto di gioco. Queste funzioni vengono chiamate molto (circa 2000-4000 volte al secondo). Le funzioni sono scritte in C per la velocità raw.estensione ctypes vs C

Ora, il modo più semplice per me di includere queste funzioni in Python è utilizzare ctypes. L'alternativa è scrivere un'estensione C in Python attorno a queste funzioni (che richiede un notevole sforzo in più). Quindi mi sono chiesto, a parte il caricamento iniziale della DLL, quanto è grande l'overhead di ctypes?


sto usando Python 2.7 (la versione standard di CPython), e non voglio usare una libreria esterna come Cython.

So che questa domanda è stata fatta prima, ma non ho visto molte informazioni sul confronto delle prestazioni tra le due opzioni.

+0

Bene, il JIT di PyPy è in grado di produrre codice molto bello per chiamate 'ctypes' da una release o due. Potresti volergli dare un colpo. Non lo invio come risposta perché non ho a disposizione dati complessi e non è chiaro se cambiare interpreti sia un'opzione per te. – delnan

+0

Mi aspetto che il sovraccarico sia simile. –

+0

@Delnan: Questo è un gioco che sto per spedire - anche a Linux. Non posso chiedere ai miei utenti di installare PyPy. – orlp

risposta

10

Ho confrontato le prestazioni di un'estensione C rispetto a un wrapper ctypes. Nel mio test particolare, la differenza era di circa 250x. C'erano più chiamate nella libreria C, quindi il wrapper ctypes stava anche eseguendo il codice Python. Il tempo di esecuzione per la libreria C è stato molto breve, il che ha reso il sovraccarico extra per il codice Python ancora più significativo. Quindi il rapporto sarà probabilmente diverso per te, ma è stato significativo nel mio caso.

+5

Quindi quale era 250x più lento? – delnan

+1

@delnan: dalla sua risposta posso leggere che l'involucro dei ctype era più lento. – orlp

6

L'interfaccia codificata C ha il potenziale per essere molto più veloce. Il collo di bottiglia è l'interfaccia da Python a C e gli argomenti di marshalling e i risultati possono ad esempio implicare la copia di stringhe o la conversione di liste Python in/da array C. Se hai un ciclo che fa diverse centinaia di queste chiamate e alcuni dati non devono essere marchiati separatamente per ogni chiamata, tutto ciò che devi fare è ricodificare il ciclo in C e potresti essere in grado di ridurre enormemente il collo di bottiglia . ctypes non ti dà questa opzione: tutto ciò che puoi fare è chiamare direttamente le funzioni esistenti.

Naturalmente tutto dipende esattamente dal tipo di funzioni che si sta chiamando e dal tipo di dati che si stanno passando. Può darsi che non sia possibile ridurre i costi generali, nel qual caso mi aspetterei che i ctypes siano più lenti ma forse non significativamente.

Il tuo miglior risultato sarebbe quello di mettere insieme un campione del tuo codice scritto in ogni modo e confrontarlo. Altrimenti ci sono troppe variabili per una risposta definitiva.

+0

I dati di cui stiamo parlando sono una maschera di bit (per collisione). i dati passati nel codice Python sono booleani, coordinate e nuove classi pymasmasmas (che contiene solo un puntatore ai dati effettivi stessi, che risiedono nel codice C.) – orlp