2012-11-06 18 views
5

Sembra che dal momento che l'accesso ai dati di array NumPy non richiede chiamate nell'interprete Python, le estensioni C possono manipolare questi array dopo aver rilasciato GIL. Ad esempio, in this thread.Accesso multithread a Python bytearra

Il tipo incorporato Python ByteArray sostiene la Buffer Protocol, un membro che è

vuoto * BUF

Un puntatore all'inizio della struttura logica descritta dai campi tampone . [...] Per gli array contigui, il valore punta all'inizio del blocco di memoria .

La mia domanda è, può un'estensione C manipolare questo buf dopo aver rilasciato le GIL (Py_BEGIN_ALLOW_THREADS), in quanto l'accesso non richiede più le chiamate alle API di Python C? O la natura del garbage collector di Python proibisce questo, dato che il bytearray e il suo buf potrebbero essere spostati durante l'esecuzione?

+1

La struttura 'Py_buffer' contiene un riferimento e' bytearray' non può essere ridimensionato fino a quando non sono state rilasciate tutte le esportazioni del buffer (ad esempio 'ob_exports> 0'). – eryksun

+0

Grazie - e suppongo anche che il buf non venga spostato (anziché rilasciato) dal GC mentre il buffer viene esportato? Python usa persino un [spostamento di GC] (http://en.wikipedia.org/wiki/Garbage_collection_ (computer_science) # Moving_vs._non-moving)? – jpavel

+0

Il 'bytearray' viene deallocato quando il conteggio dei riferimenti raggiunge 0. Il GC di Python tenta di risolvere i cicli di riferimento nei tipi di contenitore (ad es. Elenchi, classi). – eryksun

risposta

3

Per chiarire la risposta breve scritta come commento: è possibile accedere ai dati * buf senza tenere GIL, a patto che si sia sicuri che la struttura Py_buffer sia "posseduta" dal thread mentre è in esecuzione senza GIL.

Per completezza, devo aggiungere che questo può aprire la porta a rischi di arresti anomali (molto remoti): se il thread GIL-less legge i dati in * buf mentre allo stesso tempo un altro thread di mantenimento GIL è eseguendo codice Python che modifica gli stessi dati (bytearray [indice] = x), il thread GIL-less può vedere cambiamenti inaspettati dei dati sotto i suoi piedi. È vero anche l'opposto, e ancora più fastidioso (ma pur sempre teorico): se il thread GIL-less modifica i dati in * buf, allora altri thread in possesso di GIL, Python-running potrebbero vedere risultati strani o persino crash se si fa qualcosa operazioni di lettura complesse come bytearray.split().