2014-04-20 1 views
1

Je suis en train de créer un programme qui catégorise les numéros d'identification en salles et groupes. Je suis en train de commander une sortie de plusieurs processus parallèles, mais la sortie est venue comme çaCommander des données à partir de plusieurs processus dans Erlang

{'C003','Group A',1} 
{'C002','Group B',3} 
{'C015','Group C',5} 
{'C016','Group D',7} 
{'C003','Group A',2} 
{'C002','Group B',4} 
{'C015','Group C',6} 
{'C016','Group D',8} 

Mais je veux comme ceci:

{'C003','Group A',1} 
{'C003','Group A',2} 
{'C002','Group B',3} 
{'C002','Group B',4} 
{'C015','Group C',5} 
{'C015','Group C',6} 
{'C016','Group D',7} 
{'C016','Group D',8} 

Je pensais que je pourrais peut-être envoyer le Numéros à un processus et en quelque sorte les imprimer et leurs groupes dans l'ordre, mais je ne suis pas sûr de savoir comment le faire tout en ayant les processus se déroulent en parallèle. Je pensais qu'une solution pouvait être sélective mais je n'arrive pas à la comprendre non plus. Quelqu'un peut-il m'aider avec cela? Ceci est un extrait de code de mon programme principal Note: Je suis nouveau à Erlang

-module(ppp). 

-compile([export_all]). 

categorise(L) -> 

    Size = len(L) div 4, 
    Rem = len(L) rem 4,  
    spawn(ppp, cat, [self(), 'Group A', L, 0, Size + Rem]), 
    spawn(ppp, cat, [self(), 'Group B', L, (Size + Rem), Size]), 
    spawn(ppp, cat, [self(), 'Group C', L, (2*Size + Rem), Size]), 
    spawn(ppp, cat, [self(), 'Group D', L, (3*Size + Rem), Size]), 
    wait(4). 

wait(0) -> {done}; 
wait(N) -> 
receive 
    done -> wait(N-1) 
end. 

cat(P, Name, L, Start, Elements) ->  
    Extract = lists:split(Start, L), 
    Group = element(2, Extract), 
    AGroup = lists:sublist(Group, Elements), 
    spawn(ppp, putInRoom, [P, Name, AGroup]). 

putInRoom(P, _, []) -> P ! done; 

putInRoom(P, GroupName, [H|T]) -> 

if GroupName == 'Group A' ->   
    io:format("~w~n", [{'C003', GroupName, H}]),   
    putInRoom(P, GroupName, T); 
    GroupName == 'Group B' -> 
    io:format("~w~n", [{'C002', GroupName, H}]), 
    putInRoom(P, GroupName, T); 
    GroupName == 'Group C' -> 
    io:format("~w~n", [{'C015', GroupName, H}]), 
    putInRoom(P, GroupName, T); 
    GroupName == 'Group D' -> 
    io:format("~w~n", [{'C016', GroupName, H}]), 
    putInRoom(P, GroupName, T) 
end. 

len(L) -> 
    count(L, 0). 

count([], Acc) -> Acc; 

count([_|T], Acc) -> count(T, Acc + 1). 
+0

Cela n'a rien à voir avec le parallélisme et tout ce qui concerne la concurrence. Le problème est la synchronisation puisqu'il n'y en a pas entre les processus. Vous devez synchroniser la sortie d'une manière ou d'une autre. L'utilisation de sleep ne fonctionne pas lorsque vous êtes très chargé. –

+0

Donc la réponse donnée par Kadaj est correcte car il a suggéré de reproduire ces processus de manière synchrone –

Répondre

0

lieu de frai du processus putInRoom pour chaque groupe, spawn pour chaque élément dans le groupe.

-module(ppp). 

-compile([export_all]). 

categorise(L) -> 

    Size = len(L) div 4, 
    Rem = len(L) rem 4,  
    spawn(ppp, cat, [self(), 'Group A', L, 0, Size + Rem]), 
    spawn(ppp, cat, [self(), 'Group B', L, (Size + Rem), Size]), 
    spawn(ppp, cat, [self(), 'Group C', L, (2*Size + Rem), Size]), 
    spawn(ppp, cat, [self(), 'Group D', L, (3*Size + Rem), Size]), 
    wait(4). 

wait(0) -> {done}; 
wait(N) -> 
receive 
    done -> wait(N-1) 
after 2000 -> 
    ok 
end. 

cat(P, Name, L, Start, Elements) -> 
    % io:format("cat: ~p L: ~p~n", [P,L]),  
    Extract = lists:split(Start, L), 
    Group = element(2, Extract), 
    AGroup = lists:sublist(Group, Elements), 
    % io:format("AGroup: ~p~n", [AGroup]), 
    lists:map(fun(G) -> 
       spawn(ppp, putInRoom, [P, Name, G]) 
       end, AGroup). 

putInRoom(P, GroupName, H) -> 
    % io:format("putInRoom: ~p, List: ~p~n", [GroupName, H]), 
    if GroupName == 'Group A' ->   
     io:format("~w~n", [{'C003', GroupName, H}]); 
     GroupName == 'Group B' -> 
     io:format("~w~n", [{'C002', GroupName, H}]); 
     GroupName == 'Group C' -> 
     io:format("~w~n", [{'C015', GroupName, H}]); 
     GroupName == 'Group D' -> 
     io:format("~w~n", [{'C016', GroupName, H}]) 
    end, 
    P ! done. 

len(L) -> 
    count(L, 0). 

count([], Acc) -> Acc; 

count([_|T], Acc) -> count(T, Acc + 1). 

Imprime le groupe par ordre.

2> ppp:categorise(lists:seq(1,8)). 
{'C003','Group A',1} 
{'C003','Group A',2} 
{'C002','Group B',3} 
{'C002','Group B',4} 
{'C015','Group C',5} 
{'C015','Group C',6} 
{'C016','Group D',7} 
{'C016','Group D',8} 
{done} 

L'utilisation d'un retard en ajoutant timer:sleep(100), entre la ponte du processus cat. Mais alors vous sortez sur la nature concurrente. Donc, si vous voulez imprimer les messages dans l'ordre, vous devez trouver un algorithme différent.

-module(ppp). 

-compile([export_all]). 

categorise(L) -> 

    Size = len(L) div 4, 
    Rem = len(L) rem 4,  
    spawn(ppp, cat, [self(), 'Group A', L, 0, Size + Rem]), 
    timer:sleep(100), 
    spawn(ppp, cat, [self(), 'Group B', L, (Size + Rem), Size]), 
    timer:sleep(100), 
    spawn(ppp, cat, [self(), 'Group C', L, (2*Size + Rem), Size]), 
    timer:sleep(100), 
    spawn(ppp, cat, [self(), 'Group D', L, (3*Size + Rem), Size]), 
    wait(4). 

wait(0) -> {done}; 
wait(N) -> 
receive 
    done -> wait(N-1) 
after 2000 -> 
    ok 
end. 

cat(P, Name, L, Start, Elements) -> 
    % io:format("cat: ~p L: ~p~n", [P,L]),  
    Extract = lists:split(Start, L), 
    Group = element(2, Extract), 
    AGroup = lists:sublist(Group, Elements), 
    % io:format("AGroup: ~p~n", [AGroup]), 
    Pid = spawn(fun putInRoom2/0), 
    Pid ! {P, cat, {Name, AGroup}}. 

putInRoom2() -> 
    receive 
     {P, cat, {_GroupName, []}} -> P ! done; 
     {P, cat, {GroupName, L}} -> 
      F = fun(G, [H|T]) -> 
        if 
         GroupName == 'Group A' ->   
          io:format("~w~n", [{'C003', GroupName, H}]); 
         GroupName == 'Group B' -> 
          io:format("~w~n", [{'C002', GroupName, H}]); 
         GroupName == 'Group C' -> 
          io:format("~w~n", [{'C015', GroupName, H}]); 
         GroupName == 'Group D' -> 
          io:format("~w~n", [{'C016', GroupName, H}]) 
        end, 
        self() ! {P, cat, {G, T}} 
       end, 
      F(GroupName, L), 
      putInRoom2() 
    end. 

len(L) -> 
    count(L, 0). 

count([], Acc) -> Acc; 

count([_|T], Acc) -> count(T, Acc + 1). 
+0

Merci mais pourquoi cette solution les imprime-t-elle dans l'ordre? et ne créerait-il pas un processus pour chaque élément entraînant une surcharge de performance avec des listes plus grandes? –

+0

Ceci imprime dans l'ordre, car il engendre le processus dans l'ordre. Dans votre code, il imprime en réalité les colonnes "[1,2,3], [4,5,6]' signifie que vous obtenez '1,4,2,5,3,6'. Je ne sais pas pourquoi c'est. Peut-être quelque chose de planificateur? En ce qui concerne les performances, dans l'état actuel, la fonction 'putInRoom' est de très courte durée. Donc, je suppose que ce ne serait pas ce taxer. Vous pouvez mesurer la performance si. – boring

+0

La commande n'est pas ce que vous attendiez parce que vous le frai est asynchrone. Moyens, vous spawn 'cat' avec' [1,2] ',' [3,4] 'comme données, le' putInRoom' affiche '1', mais par la fois est recurse et comme le code est async, le second spawn s'exécute qui imprime '3' et de même. Vous pouvez voir que la commande d'impression change lorsque vous ajoutez un délai. Fondamentalement, vous voulez le penser comme des processus de reproduction et de transmission de messages en tant que synchronisation. – boring

Questions connexes