2011-04-11 4 views
4

J'utilise python pour des expériences de jeux vidéo en sciences cognitives. Je suis en train de tester un appareil qui détecte les mouvements oculaires via EOG, et cet appareil parle à l'ordinateur via USB. Pour s'assurer que les données sont continuellement lues à partir de l'USB pendant que l'expérience fait d'autres choses (comme changer l'affichage, etc.), j'ai pensé utiliser le module multi-traitement (avec un ordinateur multicœur bien sûr). un processus de travail distinct et utilisez une file d'attente pour informer ce travailleur lorsque des événements d'intérêt se produisent dans l'expérience. Cependant, j'ai rencontré un comportement étrange tel que même quand il y a 1 seconde entre la mise en file d'attente de 2 messages différents au travailleur, quand je regarde la sortie du travailleur à la fin, il semble avoir reçu la seconde presque immédiatement après premier. J'ai sûrement codé quelque chose d'anormal, mais je ne vois pas quoi, alors j'apprécierais beaucoup l'aide que n'importe qui peut fournir.Apparemment voyager dans le temps via le module de multi-traitement de python: sûrement j'ai fait quelque chose de mal

J'ai essayé de réduire mon code à un exemple minimal démontrant ce comportement. Si vous allez à ce point essentiel:

https://gist.github.com/914070

vous trouverez « multiprocessing_timetravel.py », qui code l'exemple, et « analysis.R », qui analyse le fichier « temp.txt » qui résulte de l'exécution "multiprocessing_timetravel.py". "analysis.R" est écrit en R et nécessite que vous ayez installé la bibliothèque plyr, mais j'ai aussi inclus un exemple de sortie d'analyse dans le fichier "analysis_results.txt" à l'historique.

+0

juste une supposition, mais votre routine d'attente occupée pourrait faire partie du problème. –

+0

@jcomeau_ictx: merci pour la suggestion, mais le remplacement de toutes les instances de wait (...) par time.sleep (1) donne le même comportement. –

+0

Je ne suis pas familier avec ce module, donc votre code ressemble à du charabia, mais si le file-writer et le file-reader sont sur des threads séparés écrivant dans la même file, vous n'avez aucun moyen de savoir quand le verrou à la file d'attente * (rappelez-vous, l'écrivain peut être interrompu pendant un certain temps tout en maintenant le verrou) *, la seule façon de vraiment savoir quand les données sont entrées dans l'écrivain est d'inclure le * temps reçu * dans le cadre de l'objet que vous faites la queue –

Répondre

0

Ah, je l'ai résolu et il s'est avéré être beaucoup plus simple que prévu. Il y a eu 5 événements par "essai" et l'événement final a déclenché une écriture de données sur le HD. Si cette écriture finale prend beaucoup de temps, le travailleur peut ne pas attraper le premier événement du prochain essai jusqu'à ce que le deuxième événement ait déjà été mis dans la file d'attente. Lorsque cela se produit, le premier événement dure (aux yeux du travailleur) pour une seule de ses boucles avant qu'il ne rencontre le deuxième événement. Je devrais soit trouver un moyen plus rapide d'écrire les données ou de laisser les données en mémoire jusqu'à ce qu'une pause dans l'expérience permette une écriture longue.

1

En dépit du traitement multi-traitement, votre file d'attente utilise toujours des objets de synchronisation (deux verrous et un sémaphore) et la méthode put engendre un autre thread (basé sur la source 2.7). Donc la contention de GIL (et d'autres choses amusantes) peut entrer en jeu, comme suggéré par BlueRaja. Vous pouvez essayer de jouer avec sys.checkinterval et de voir si la diminuer diminue également l'écart observé, bien que vous ne vouliez pas courir normalement dans cette condition. Notez que si votre code de lecture USB supprime le GIL (par exemple le code ctypes, ou un module d'extension Python conçu pour abandonner le GIL), vous obtiendrez un vrai multithreading, et une approche threadée pourrait être plus productive que l'utilisation du multitraitement.

Questions connexes