std.parallelism

Модуль std.parallelism реалізує примітиви високого рівня для зручного паралельного програмування.

parallel

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 визначає кількість елементів, які мають оброблятися на кожен робочий потік.

reduce

Функція 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;

Поглиблення

rdmd playground.d