Модуль 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 є "основою (seed)"
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;