Помимо параллелизации, вы не хотите вычислять sqrt (До) на каждой итерации. Вы также можете принять множители 2, 3 и 5 и рассчитать только для N% 6 в {1,5} или N% 30 в {1,7,11,13,17,19,23,29}.
Вы сможете легко распараллелить алгоритм факторинга, поскольку N-й этап зависит только от sqrt (n) -го результата, поэтому через некоторое время не будет никаких конфликтов. Но это не очень хороший алгоритм, поскольку он требует большого деления.
Вы также должны иметь возможность распараллеливать алгоритмы просеивания, если у вас есть рабочие пакеты средства записи, которые гарантированно завершаются перед чтением. В основном, авторы не должны конфликтовать с читателем - по крайней мере, после того, как вы сделали несколько записей, они должны работать по крайней мере на N выше читателя, поэтому вам нужно только синхронизированное чтение довольно редко (когда N превышает последнее синхронизированное чтение значение). Вам не нужно синхронизировать массив bool с любым количеством потоков записи, поскольку конфликты записи не возникают (в худшем случае более одного потока записывают значение true в одно и то же место).
Основная проблема заключается в том, чтобы обеспечить завершение работы любого работника, ожидающего записи. В C ++ вы использовали бы сравнение и набор для переключения на работника, которого ожидают в любой момент. Я не C # Wonk, поэтому не знаю, как сделать это на этом языке, но функция Win32 InterlockedCompareExchange должна быть доступна.
Вы также можете попробовать подход, основанный на актерах, так как таким образом вы можете планировать актеров, работающих с наименьшими значениями, что может быть легче гарантировать, что вы читаете действительные части решета без необходимости блокировки шины каждый шаг N.
В любом случае, вы должны убедиться, что все работники получили значение выше N до того, как вы его прочитаете, а стоимость выполнения - это то, где компромисс между параллелью и последовательностью достигнут.