Модуль std.parallelism реализует высокоуровневые
примитивы для удобной организации параллельного программирования.
std.parallelism.parallel позволяет автоматически распределить
тело цикла foreach между разными потоками:
// параллельно возвести в квадрат
// элементы arr
auto arr = iota(1,100).array;
foreach(ref i; parallel(arr)) {
i = i*i;
}
Внутри parallel используется оператор opApply.
Глобальная функция parallel - это упрощённый
вариант вызова taskPool.parallel. Она применяет
TaskPool, использующий количество рабочих потоков,
равное общему числу процессоров - 1. Создание
отдельного пула позволяет назначить степень
параллелизма.
Обратите внимание, тело parallel-итерации не
должно изменять элементы, к которым может иметь
доступ другая рабочая единица.
Опциональный параметр workingUnitSize задаёт
количество элементов, обрабатываемых каждым
потоком.
Функция
std.algorithm.iteration.reduce,
известная в других функциональных контекстах как accumulate
или foldl, вызывает функцию fun(acc, x) для каждого элемента
x, передавая через acc предыдущий результат:
// 0 - начальное значение
auto sum = reduce!"a + b"(0, elements);
Taskpool.reduce -
это параллельный аналог reduce:
// Вычислить сумму диапазона параллельно, используя
// первый элемент каждой рабочей единицы как начальное значение
auto sum = taskPool.reduce!"a + b"(nums);
TaskPool.reduce разделяет диапазон на поддиапазоны,
которые обрабатываются параллельно. Как только результаты
от отдельных поддиапазонов становятся известны,
они так же обрабатываются.
task()task - это обёртка для функции,
исполнение которой может занять значительное время
или которую следует исполнить в собственном рабочем
потоке. Её можно поставить в очередь пула задач:
auto t = task!read("foo.txt");
taskPool.put(t);
или же непосредственно исполнить в отдельном новом потоке:
t.executeInNewThread();
Чтобы получить результат задачи, необходимо вызвать yieldForce.
Этот вызов блокирует текущий поток до тех пор, пока
не будет получен результат.
auto fileData = t.yieldForce;