2013-08-12 5 views
7

J'écris actuellement sur un programme, où je dois faire face à d'énormes tableaux. Je peux cependant diviser ces tableaux. Mon plan est maintenant, de traiter les tableaux dans différents travailleurs Web. Je n'ai cependant jamais travaillé avec eux et j'ai plusieurs questions:HTML5/JS - Démarrer plusieurs webworkers

1. Comment exécuter plusieurs travailleurs Web? J'ai essayé une boucle for regarder comme ça:

for(i = 0; i < eD.threads; i++){ 
    //start workers here 
    var worker = new Worker("js/worker/imageValues.js"); 
    worker.postMessage(brightness, cD.pixels[i]); 
} 

Ici, je reçois l'erreur, que l'objet n'a pas pu être cloné. Ce qui semble logique. Je suppose qu'il serait préférable de les enregistrer dans un tableau?

2. Comment contrôler que tous ont fini leur travail? (J'ai besoin de réassembler le tableau et de travailler avec lui plus tard)

3. Combien de travailleurs Web apportent-ils vraiment une amélioration?

4. Existe-t-il un didacticiel avancé, en plus de l'entrée MDN?

Merci!

+0

Pour # 2: Il faudrait utiliser 'postMessage' du travailleur de renvoyer une message à ce parent JS disant que le travailleur a terminé le traitement (et probablement passer les résultats) ...vous devrez donc ajouter un écouteur 'onmessage' pour chaque travailleur, dans la boucle. Vous stockez toutes ces réponses dans un tableau. Lorsque le nombre de réponses dans le tableau est le même que le nombre de travailleurs créés, cela signifie que tout est fait ... et vous pouvez gérer ce tableau que vous avez créé. Cela peut être rendu plus «propre» en utilisant le concept des objets différés de jQuery. – Ian

+1

«Ne peut pas être cloné» signifie que ce que vous transmettez à l'ouvrier n'a pas pu être cloné. Pour éviter les conditions de concurrence, les objets ne sont jamais partagés entre les travailleurs et le thread principal. Les objets doivent soit être copiés dans l'espace mémoire du worker, soit (avec des Blob et des tableaux typés) le thread principal peut abandonner de l'espace mémoire à un worker et perdre la référence à l'objet. – apsillers

+0

Ok. Lisez à ce sujet, mais l'ai oublié. En tous cas. Si je crée une variable temporaire dans la boucle, sécuriser le tableau en tant que chaîne et transmettre cette chaîne, serait-ce une meilleure solution? Quelque part j'ai lu, que j'envoie seulement des cordes aux ouvriers, ailleurs dit-il, que je peux transférer des variables? Merci à vous deux pour votre explication, aidez-moi à commencer! –

Répondre

14

1. Comment exécuter plusieurs travailleurs Web? J'ai essayé une boucle forcée ressemblant à ceci:

Il n'y a aucun problème avec la création de plus d'un travailleur, même si vous ne gardez pas trace d'eux dans un tableau. Voir ci-dessous.

2. Comment contrôlerais-je que tous ont fini leur travail? (Je dois réassemblage le tableau et travailler avec elle plus tard)

Ils peuvent poster un message à vous quand ils sont faits, avec les résultats. Exemple ci-dessous

3. Combien de travailleurs Web apportent-ils vraiment une amélioration?

Quelle est la longueur d'un morceau de ficelle? :-) La réponse dépendra entièrement de la machine cible sur laquelle elle est en cours d'exécution. Beaucoup de gens ont aujourd'hui quatre noyaux ou plus sur leurs machines. Bien sûr, la machine fait beaucoup d'autres choses aussi. Vous devrez syntoniser votre environnement cible.

4. Existe-t-il un didacticiel avancé, en plus de l'entrée MDN?

Il n'y a pas beaucoup de "avancé" sur les web workers. :-) J'ai trouvé this article était suffisant.

Voici un exemple cinq travailleurs en cours d'exécution et de regarder pour eux à faire:

fenêtre principale:

(function() { 
    var n, worker, running; 

    display("Starting workers..."); 
    running = 0; 
    for (n = 0; n < 5; ++n) { 
     workers = new Worker("worker.js"); 
     workers.onmessage = workerDone; 
     workers.postMessage({id: n, count: 10000}); 
     ++running; 
    } 
    function workerDone(e) { 
     --running; 
     display("Worker " + e.data.id + " is done, result: " + e.data.sum); 
     if (running === 0) { // <== There is no race condition here, see below 
      display("All workers complete"); 
     } 
    } 
    function display(msg) { 
     var p = document.createElement('p'); 
     p.innerHTML = String(msg); 
     document.body.appendChild(p); 
    } 
})(); 

worker.js:

this.onmessage = function(e) { 
    var sum, n; 
    sum = 0; 
    for (n = 0; n < e.data.count; ++n) { 
     sum += n; 
    } 
    this.postMessage({id: e.data.id, sum: sum}); 
}; 

A propos de la condition de la race qui n'existe pas : Si vous pensez en termes de threading préemptive vrai, alors vous pourriez penser: Je pourrais créer un travailleur, incrémenter running à 1, puis avant de créer le prochain travailleur, je pourrais obtenir le message de la première qu'il a fait, décrémenter running à 0, et pense à tort que tous les travailleurs ont été faits. Cela ne peut pas se produire dans l'environnement des travailleurs Web. Bien que l'environnement soit bienvenu pour démarrer le travailleur dès qu'il le souhaite, et un travailleur pourrait bien finir avant que le code de démarrage des travailleurs ne finisse, tout ce qu'il ferait file d'attente un appel à la fonction workerDone pour le thread JavaScript principal. Il n'y a pas de préemption. Et donc nous savons que tous les travailleurs ont été démarrés avant le premier appel à workerDone est effectivement exécuté. Ainsi, quand running est 0, nous savons qu'ils sont tous finis.

Note finale: Dans ce qui précède, j'utilise onmessage = ... pour raccorder des gestionnaires d'événements. Naturellement, cela signifie que je ne peux avoir qu'un gestionnaire d'événements sur l'objet avec lequel je fais cela. Si vous devez disposer de plusieurs gestionnaires pour l'événement message, utilisez addEventListener. Tous les navigateurs qui prennent en charge les travailleurs Web prennent en charge addEventListener sur eux (vous ne devez pas vous inquiéter de la chose IE attachEvent).

+0

Salut, merci pour votre réponse. Je vais y travailler. Les morceaux de String sont en réalité imagaData d'une toile transformée en chaîne. Pour une résolution de 1300 * 1700px vous vous retrouvez avec un tableau avec la longueur de 8840000. Donc j'ai pensé que je diviser le tableau en x morceaux (en fonction d'un nombre de threads contrôlable par l'utilisateur). Chaque partie du tableau va être traitée. Ensuite, imageData-array est reconstruit et dessiné sur un canevas. Au moins selon mon plan: D –

+3

@stiller_leser: On dirait le genre de chose pour laquelle les web workers étaient destinés. :-) Mais je ne parlais pas de cordes dans le sens de l'informatique. "Quelle est la longueur d'une ficelle?" est un idiome britannique, signifiant fondamentalement "il y a trop de variables pour répondre à cela." –

+0

: D - Je ne m'attendais pas à un idiome ici. N'avez pas eu trop d'idiomes à l'école, si longtemps: Vous vivez et apprenez. –

0

stiller_leser. Si vous travaillez toujours sur le problème, jetez un oeil au plugin ng-vkthread. Il vous permet de mettre en œuvre une technique de calcul parallèle, que vous essayez de développer dans votre projet. Avec ce plugin, vous pouvez exécuter plusieurs fonctions dans plusieurs threads simultanément.

La fonction peut être définie directement dans le thread principal ou appelée à partir d'un fichier javascript externe.

Fonction peut être:

  • fonctions régulières
  • méthodes de l'objet
  • Fonctions avec dépendances
  • Fonctions avec contexte
  • Les fonctions anonymes

Utilisation de base:

/* function to execute in a thread */ 
function foo(str) { 
    return str.toUpper(); 
} 

function bar(str) { 
    return str.toUpper(); 
} 

// to execute these 2 functions in 2 threads: // 

/* create objects, which you pass to vkThread as an argument*/ 
var param1 = { 
     fn: foo, 
     args: ['hello'] 
    }; 
var param2 = { 
     fn: bar, 
     args: ['world'] 
    } 

/* run thread */ 
vkThread.execAll([param1,param2]).then(
    function (data) { 
    $scope.repos = data[0] + ' ' + data[1]; // <-- HELLO WORLD 
    } 
); 

Exemples et API doc: http://www.eslinstructor.net/ng-vkthread/demo/

Hope this helps,

--Vadim

Questions connexes