Le module std.parallelism
fourni des primitives de haut-niveau pour faciliter la programmation concurrente.
std.parallelism.parallel
permet de distribuer automatiquement le corps d'un foreach
sur différents threads:
// mise au carré d'un tableau en parallèle
auto tab = iota(1,100).array;
foreach(ref i; parallel(tab))
{
i = i*i;
}
parallel
utilise l'opérateur opApply
en interne. La méthode parallel
est un raccourci pour taskPool.parallel
qui est une TaskPool
qui utilise le nombre de cpus - 1 threads. Créer sa propre instance de l'objet permet de contrôler le degré de parallélisme.
Il faut faire attention à ce que le corps de l'itération de parallel
ne modifie pas des variables que d'autres threads pourraient utiliser.
L'option workingUnitSize
spécifie le nombre d'éléments gérés par chaque thread.
La fonction std.algorithm.iteration.reduce
, connue dans d'autres langages fonctionelles sous le nom de accumulate ou de fold, appelle la fonction fun(acc, x)
pour chaque élément x
où acc
est le résultat de l'appelle précédent:
// 0 est la valeur de départ
auto sum = reduce!"a + b"(0, elements);
Taskpool.reduce
est une version parallèle de reduce
:
// Détermine la somme des éléments d'une range
// en parallèle, en utilisant le premier élément
// de la range comme valeur de départ de acc
auto sum = taskPool.reduce!"a + b"(nums);
TaskPool.reduce
sépare la range en sous-ranges qui sont réduites en parallèle. Une fois que ces résultats ont été calculés, les résultats sont réduits eux-mêmes.
task()
task
est une fonction qui permet d'appeler une autre fonction, qui pourrait prendre longtemps ou qui devrait être exécutée dans son propre thread. Il peut soit être mis dans la file d'attente d'une taskpool:
auto t = task!read("foo.txt");
taskPool.put(t);
soit être directement exécuté sur un nouveau thread:
t.executeInNewThread();
Pour obtenir le résultat de la tâche, il faut appeler la méthode yieldForce
de l'objet. Elle bloquera l'exécution jusqu'à ce que le résultat soit disponible.