2010-02-15 4 views
0

Ceci est très étrangeLa lecture d'un fichier binaire en Python: prend beaucoup de temps pour lire certains octets

Je lis un peu (il est vrai très grand: ~ 2 Go chacun) des fichiers binaires à l'aide des bibliothèques numpy en Python. J'utilise le:

thingy = np.fromfile(fileObject, np.int16, 1) 

méthode. Ceci est juste au milieu d'une boucle imbriquée - je fais cette boucle 4096 fois par 'canal', et cette boucle 'canal' 9 fois pour chaque 'récepteur', et cette boucle 'récepteur' 4 fois (il y a 9 canaux par récepteur, dont il y a 4!). C'est pour chaque "bloc", dont il y a ~ 3600 par fichier.

Donc, vous pouvez voir, très itératif et je sais que cela prendra du temps, mais cela prenait BEAUCOUP plus de temps que prévu - en moyenne 8,5 secondes par 'bloc'. J'ai exécuté quelques tests en utilisant time.clock() etc. et j'ai trouvé que tout fonctionnait aussi vite qu'il le devrait, sauf pour environ 1 ou 2 échantillons par 'block' (donc 1 ou 2 en 4096 * 9 * 4) où il semblerait être «coincé» pendant quelques secondes. Maintenant, cela devrait être un cas de retourner un simple int16 de binaire, pas exactement quelque chose qui devrait prendre quelques secondes ... pourquoi est-il coller? De l'analyse comparative, j'ai trouvé qu'il collait au même endroit à chaque fois, (bloc 2, récepteur 8, canal 3, échantillon 1085 était l'un d'entre eux, pour l'enregistrement!), Et il serait coincé là pour environ la même quantité de temps chaque course.

Des idées ?!

Merci,

Duncan

+0

Comptage à partir de 0 Je présume? –

+0

Oui, donc les récepteurs 0-3, les canaux 0-7, les échantillons 0-4095 –

+0

Le problème avec quelque chose comme 'fromfile()' est qu'il ne peut pas savoir à l'avance combien d'espace allouer, donc avec des fichiers vraiment volumineux vous pourrait être vissé. Voir ma réponse et certains des commentaires suivants dans http://stackoverflow.com/questions/1896674/python-how-to-read-huge-text-file-into-memory pour des idées possibles sur la façon de gérer cela, et la problème sous-jacent. –

Répondre

3

Bien qu'il soit difficile de dire sans une sorte d'échantillon reproductible, cela ressemble à un problème de mise en mémoire tampon. La première partie est mise en mémoire tampon et jusqu'à ce que vous atteigniez la fin du tampon, elle est rapide; alors il ralentit jusqu'à ce que le tampon suivant soit rempli, et ainsi de suite.

+0

Oui, cela semble probable, savez-vous d'une façon que je pourrais tester cela? Ou quelle est la taille probable du tampon? –

+0

Eh bien, une chose pour au moins déterminer si gnibbler ou je suis plus proche de la solution est de l'exécuter et de jeter instantanément les résultats. Si le ralentissement se produit encore, il est plus susceptible d'être un problème de mise en mémoire tampon. Alors peut-être voir si lire manuellement au lieu de passer par 'numpy' change quelque chose. –

+0

Bien sûr, désolé de continuer à poser de nouvelles questions mais comment «jeter» un objet en Python? J'ai essayé de trouver à propos de disposer etc. pour les âges mais je ne le trouve nulle part. –

2

Où stockez-vous les résultats? Lorsque les listes/dicts/what deviennent très volumineux, il peut y avoir un retard notable quand ils doivent être réaffectés et redimensionnés.

+0

Eh bien, essentiellement, ils sont tous stockés dans des listes dans les listes , puis l'ensemble complet de données (par 'bloc') est stocké dans une instance d'une classe, avec des informations d'en-tête. Cela ne devrait pas être plus qu'un mégaoctet vraiment ... À moins que Python ne dispose pas de listes? Puis-je le forcer à le faire? –

1

Se pourrait-il que garbage collection soit en train d'entrer dans les listes?

Ajouté: est-ce des données amusantes, ou blockno? Que se passe-t-il si vous lisez les blocs dans un ordre aléatoire, le long des lignes

r = range(4096) 
random.shuffle(r) # inplace 
for blockno in r: 
    file.seek(blockno * ...) 
    ... 
Questions connexes