Опубликован: 15.10.2009 | Доступ: свободный | Студентов: 896 / 248 | Оценка: 4.42 / 4.20 | Длительность: 08:22:00
Специальности: Программист
Лекция 11:

Решето Эратосфена для нахождения простых чисел

< Лекция 10 || Лекция 11: 12 || Лекция 12 >
Аннотация: В этой лекции рассмотрена теория и реализация алгоритма Эратосфена при нахождения простых чисел в контексте параллельного программирования.

Рассмотрим задачу отыскания всех простых чисел в интервале от 2 до некоторого заданного числа n. Выделим в исходном списке 2,3, \dots , n первое число, которое будет простым, и затем зачеркнем как само число 2, так и все числа в списке, кратные ему. Чтобы зачеркнуть эти кратные числа, достаточно зачеркнуть каждое второе число в списке, начиная с числа 2. Затем выделяем первое незачеркнутое число в качестве очередного простого - им будет число 3, и проводим аналогичную процедуру, зачеркивая каждое третье число, начиная с числа 3. Продолжаем эту процедуру до тех пор, пока не дойдем до очередного простого числа p, такого что p^2 \ge n. Легко видеть, что все оставшиеся незачеркнутыми числа в интервале p, \dots, n являются простыми. Описанный метод нахождения простых чисел носит название решета Эратосфена.

В этом разделе будет описан параллельный вариант алгоритма решета Эратосфена (http://software.intel.com/en-us/articles/parallel-reduce/ ), взятый из примеров к библиотеке Intel Threading Building Blocks ( http://www.threadingbuildingblocks.org/), и реализованный с использованием средств библиотеки PFX.

Параллельный алгоритм поиска простых чисел на основе решета Эратосфена

Будем рассматривать задачу нахождения количества простых чисел в интервале от 2 до n ( n \ge 2 ). (В действительности, в программе будет иметься специальный ключ, задание которого будет приводить также к распечатке всех найденных простых чисел).

Идея алгоритма состоит в разбиении поиска на 2 этапа: на 1-ом этапе, который выполняется последовательно, находятся все простые числа в диапазоне 2\dots\sqrt{n} с помощью классического метода решета Эратосфена. Найденные простые числа, на 2-ом этапе, позволяют вычеркнуть все составные числа в диапазоне \sqrt{n}\dots n . Параллелизация заключается в том, что диапазон \sqrt{n}\dots n разбивается на поддиапазоны размера m, где m=round.up.to.even.(\lfloor\sqrt{n}\rfloor), в которых поиск простых чисел может происходить независимо.

В приведенном ниже алгоритме учитываются также следующие свойства задачи:

  1. поскольку все четные числа, за исключением числа 2, являются составными, то в каждом поддиапазоне размера m рассматриваются только нечетные числа; следствием этого является то, что размер соответствующих массивов равен m/2 ;
  2. в силу выбора размера диапазона равным m, количество поддиапазонов, рассматриваемых на 2-ом этапе, также не будет превышать m, что, одновременно, является верхней границей максимального числа потоков для обработки.
Описание 1-ой стадии

Назначение первой стадии ? отыскать все простые числа в поддиапазоне 2\dots\sqrt{n} , которые затем будут использоваться для нахождения простых чисел в следующих поддиапазонах.

В начале 1-ой стадии, размещаются массивы is_composite и prime_steps размерности m/2, где первый массив служит для процедуры просеивания, а во втором массиве сохраняются найденный на этой стадии простые числа. В массиве is-composite элемент с номером i соответствует нечетному числу 2_i+1. Сам алгоритм состоит в обычном просеивании Эратосфена, начиная с элемента массива is_composite с номером i=1, т.е., простого числа 3 (простое число 2 учитывается специальным образом).

Описание 2-ой стадии

Вторая стадия алгоритма заключается в одновременной обработке m поддиапазонов, укладывающихся в интервале \sqrt{n}\dots n , с помощью нескольких потоков.

Каждый поток, в общем случае, обрабатывает несколько поддиапазонов, сохраняя количество найденных в них простых чисел в соответствующем элементе массива count_primes. После окончания работы всех потоков (т.е., после выхода из цикла Parallel.For), находится сумма всех элементов массива count_primes, которая добавляется к количеству найденных простых чисел на первом этапе. Это значение - totalCountPrimes и становится результатом решения задачи.

Ключевым моментом 2-ой стадии является обработка потоком одного поддиапазона, начинающегося с числа start, и имеющего размер m. Для начала непосредственного просеивания в этом поддиапазоне, необходимо для каждого простого числа f, найденного на первой стадии, вычислить смещение от начала данного поддиапазона ? т.е., позицию, начиная с которой будет происходить зачеркивание чисел с определенным шагом, равным f.

Вычисление данного смещения содержательно можно разбить на 4 шага:

  1. определяем число, на котором "остановился" процесс зачеркивания в предыдущем поддиапазоне для данного f ; это число определяется по формуле
    k = ( start - 1 ) / f * f
  2. так как все поддиапазоны, в том числе и предыдущий, имеют размер m , то от начала этого поддиапазона число k отстоит на расстоянии
    p = k \% m
  3. поскольку в каждом поддиапазоне проверяются на простоту только нечетные числа, то позиция (отсчитываемая от начала предыдущего поддиапазона) следующего нечетного числа (т.е., числа с которого начнется просеивание в текущем поддиапазоне) определяется как

    l = p + f, если p четно,

    и l = p + 2*f, если p нечетно

  4. наконец, определяем позицию относительно данного поддиапазона полученного на предыдущем шаге нечетного числа, учитывая, что в поддиапазоне рассматриваются только нечетные числа:
    fpos =  l / 2 - m / 2

Рассмотрим пример вычисления смещения в соответствии с шагами, представленными выше.

Пусть n = 100, тогда m = 10, и простыми числами, найденными в первом поддиапазоне, являются 3,5,7.

Рассмотрим, допустим, третий по счету поддиапазон, задаваемый, соответственно параметрами start = 20 и f = 3. Тогда

k = ( 20 -1 ) / 3 * 3 = 18

Т.е., последнее число, кратное 3, в предыдущем поддиапазоне есть число 18, которое отстоит от начала предыдущего поддиапазона на расстоянии

p = 18 % 10 = 8

Т.к. p четно, то позиция следующего нечетного числа определяется как

l = 8 + 3 = 11

(легко заметить, что эта позиция соответствует числу 21). Тогда, число 21, с которого мы начнем зачеркивание чисел в третьем поддиапазоне с шагом 3, имеет смещение относительно начала этого диапазона

fpos = 11 / 2 - 10 / 2 = 0

Действительно, число 21 является первым нечетным числом в 3-ем поддиапазоне, а потому оно имеет смещение 0 от начала этого поддиапазона.

< Лекция 10 || Лекция 11: 12 || Лекция 12 >
Максим Полищук
Максим Полищук
"...Изучение и анализ примеров.
В и приведены описания и приложены исходные коды параллельных программ..."
Непонятно что такое - "В и приведены описания" и где именно приведены и приложены исходные коды.