Многопоточность в D с для цикла
Я знаю, что Rust может запускать циклы с легкими нитями. Что-то вроде:
use task::spawn;
fn main() {
for 100.times {
do spawn {
io::println("Hello");
}
}
Как я могу сделать это в D?
2 ответа
Соответствующий документ API: std.parallelism
Вот несколько способов выполнить ваш пример:
Параллельный foreach, используя параллель TaskPool:
foreach (i, val; taskPool.parallel(new int[50])) {
writeln("Hello:", i);
}
Обычный foreach, добавление задач в пул задач с помощью команды put:
foreach (i; 0 .. 50) {
auto t = task!writeln("Hello:", i);
taskPool.put(t);
}
Выполните каждую задачу в новом потоке вместо TaskPool:
foreach (i; 0 .. 50) {
auto t = task!writeln("Hello:", i);
t.executeInNewThread();
}
Среда выполнения Rust имеет встроенный планировщик задач, но с D это реализовано в виде библиотеки. При этом второе является наиболее близким с точки зрения функциональности, а последнее - наиболее близким по синтаксису (но это потоки ОС, а не легковесные).
В D легкие потоки явно контролируются программистом. TaskPool
аналогичен планировщику в Rust/Go, но дает более детальный контроль программисту. Это делает его немного более многословным, но также дает вам параллельные версии map
, reduce
, foreach
и т. д. Это позволяет эффективно представлять более сложные алгоритмы.
Выполнение каждого примера должно дать ожидаемый результат: неправильные записи.
Замечания:
Из документа:
Рабочие потоки в этом пуле являются потоками демонов, то есть нет необходимости вызывать TaskPool.stop или TaskPool.finish перед завершением основного потока.
Второй пример не ожидает, пока все рабочие не будут выполнены, поэтому при тестировании вы можете не получить результатов (когда основной закончит работу, все оставшиеся задачи будут убиты). Возможно, вам придется заблокировать, вызвав финиш:
taskPool.finish(true);
D не имеет встроенных абстракций для легких потоков. Вместо этого вы можете:
- использовать потоки (см. std.concurrency и std.parallelism)
- использовать волокна и многозадачность вручную, явно приводя к выполнению
- использовать библиотеку, такую как Vibe.d, которая реализует асинхронный ввод-вывод с использованием волокон и неявной выдачи при операциях блокировки