2017-07-12 8 views
0

je le code de test qui effectue les opérations suivantes:barrière MPI ne bloque pas écriture de fichiers, chasse d'eau et os.fsync

Ecrire un message de test à un fichier> Barrière> Lire le message de test> Affirmer égal> Répéter.

from __future__ import print_function 
import os 
from mpi4py import MPI 


comm = MPI.COMM_WORLD 
rank = comm.Get_rank() 
loop = True 


def main(): 
    global loop 
    txt_write = 'buhahaha' 

    with open('test', 'w') as f1: 
     if rank == 0: 
      f1.write(txt_write) 

     f1.flush() 
     os.fsync(f1.fileno()) 

    comm.barrier() 

    with open('test') as f2: 
     txt_read = f2.read() 

    try: 
     assert txt_read == txt_write 
    except: 
     print("Assertion error", txt_read, "!=", txt_write, 'rank=', rank) 
     loop = False 
    finally: 
     comm.barrier() 
     if rank == 0: 
      os.remove('test') 


if __name__ == '__main__': 
    i = 0 
    while loop: 
     main() 
     if i % 1000 == 0 and rank == 0: 
      print("Iterations:", i) 

     i += 1 

Il fonctionne pour quelques 100 ou 1000 itérations, mais à un moment donné, il lit un fichier vide et l'assertion échoue. D'autres réponses avaient recommandé l'utilisation de flush et os.fsync, mais cela ne semble pas aider - cela rend l'exécution plus lente. Une idée de comment résoudre ce problème?

+0

Qu'est-ce que le système de fichiers utilisez-vous? Est-ce un seul noeud ou un cluster? – Zulan

+1

L'ouverture d'un fichier en écriture n'est-elle généralement pas tronquée pour être vide? Donc, vos threads ne courent-ils pas entre la plupart d'entre eux en les tronquant pour être vides et l'un tronque-t-il en y écrivant une chaîne? – jschultz410

+0

@zulan ext4 filesytem sur linux. J'ai couru ce code avec 2 processus sur un poste de travail. – jadelord

Répondre

3

Peut-être que vous pouvez essayer quelque chose comme ça, à la place:

if rank == 0: 
    with open('test', 'w') as f1: 
    f1.write(txt_write) 
    # as @jschultz410 correctly pointed out, 
    # we remove f1.flush() and f1.close() 

comm.barrier() 

with open('test') as f2: 
    txt_read = f2.read() 
+0

Cela semble fonctionner. Pourquoi donc? Pourriez-vous expliquer? – jadelord

+0

Vous avez eu un problème d'indentation. Une partie du code était juste pour le rang 0 et une partie était pour chaque rang. Et, vous étiez en train d'ouvrir le même fichier avec tous les rangs pour l'écriture. – mko

+0

Je ne pense pas que c'était un problème d'indentation. C'était un problème logique. Il semble que vous vous attendiez 'open (fname, 'w')' à n'avoir aucun effet sur le fichier. Aussi, pourquoi avez-vous les lecteurs ouvrir le fichier pour l'écriture du tout? Pourquoi ne pas simplement avoir le fil de rang 0 être le seul à l'ouvrir pour l'écriture? Alors que les threads non-rang 0 sautent directement à l'attente sur la barrière, puis lire? – jschultz410

0

Le code a donné lieu à un race condition où tous les processus s'ouvraient le même fichier en même temps. Merci à @ jschultz410 et @mko pour avoir identifié cette erreur logique.

Ma solution pour le code était d'utiliser un flux de mémoire au lieu d'un vrai fichier. Maintenant, la ouverte, écrire et lire parties du code Devient:

from io import StringIO 

f1 = StringIO() 
if rank == 0: 
    f1.write(txt_write) 

f1.flush() 
comm.barrier() 

txt_read = f1.getvalue()