На ruby делается так:Интересный огород.
foreach
наParallel.Invoke(() => DoSomeWork(), () => DoSomeOtherWork());
Количество потоков подобрать под конкретное железо, либо (если есть желание заморочиться) можно сделать настраиваемым - начать с 4 потоков, считать среднюю скорость обработки узлов (кол-во узлов в минуту), вводить по одному потоку в минуту, измеряя, увеличилось ли время или уменьшилось. Если время увеличилось - возвращаем прежнее количество, если уменьшилось - добавляем ещё поток, пока не найдём оптимальный вариант.