Я реализовал решето Эратосфена, чтобы узнать простые числа, используя метод openMp для различных значений терминов и потоков.
Вот мой код
// Type your code here, or load an example.
#include <stdio.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>
#include<omp.h>
void SieveOfEratosthenes(int n)
{
bool prime[n + 1];
memset(prime, true, sizeof(prime));
const int end_p=sqrt(n);
#pragma omp parallel for
for (int p = 2; p <= end_p; p++)
{
bool prime_p;
#pragma omp atomic read
prime_p=prime[p];
if (prime_p == true)
{
for (int i = p * p; i <= n; i += p)
{
#pragma omp atomic write
prime[i] = false;
}
}
}
for (int p = 2; p <= n; p++)
if (prime[p])
printf("%d ", p);
}
int main(int argc, char* argv[]){
int procs;
int term =100;
double start,finish;
procs = omp_get_num_procs();
omp_set_num_threads(procs);
start = omp_get_wtime();
SieveOfEratosthenes(term);
finish = omp_get_wtime();
printf("Elapsed time = %e seconds\n", finish - start);
return 0;
}
Я собираюсь показать вывод затраченного времени для различных терминов и потоков.
Вот результат:
1.term=100
a)Thread 1 , elapsed time= 3.879014e-04 seconds
b)Thread 2, elapsed time = 3.887471e-04 seconds
c)Thread 4, elapsed time = 3.742063e-04 seconds
d)Thread 8, elapsed time = 3.988100e-04 seconds
e)Thread 16, elapsed time = 5.262811e-04 seconds
2.term = 100000
a)Thread 1, elapsed time = 6.131708e-03
b)Thread 2, elapsed time = 4.231855e-03
c)Thread 4, elapsed time = 4.193152e-03
d)Thread 8, elapsed time = 6.109135e-03
e)Thread 16, elapsed time = 4.225969e-03
3.term = 100000000
a)Thread 1, elapsed time = 1.237387e+01
b)Thread 2, elapsed time = 1.184531e+01
c)Thread 4, elapsed time = 1.160130e+01
d)Thread 8, elapsed time = 1.128761e+01
e)Thread 16, elapsed time = 1.18116e+01seconds
Теперь я вижу по статистике, когда срок равен 100, прошедшее время увеличивается для потока 8,16 (1-d), e))
При term = 100000 истекшее время увеличивается для потока 8(2 d)), затем снова уменьшается.
Когда term = 100000000, прошедшее время увеличивается для количества потоков 16, чем количество потоков 8.
Меня смущает то, что задача, разделенная на количество прошедших потоков, должна уменьшаться. Я имею в виду, если количество потоков увеличилось, прошедшее время уменьшилось. Тем не менее, я увидел изменение в моем результате.
Было бы здорово, если бы кто-нибудь помог мне узнать, что я пропустил в своем коде.
Спасибо.
Я видел, что атомарная операция никак не повлияла на код. Я получил тот же результат с ними без них. для компиляции$ gcc -O2 -fopenmp -o prime prime.c
, для интерактивной сессии `srun -p node -n 10 -N 1 --pty --mem 10000 -t 10:00 bash, for execution
./prime 4`, где 4 — номер потока.
Используйте omp_set_num_threads(thread_count);
в своем main
, чтобы установить количество потоков.
Исключите распечатку из измерения скорости, так как она не имеет отношения к расчету и является самой медленной частью вашего кода.
Используйте динамическое расписание #pragma omp parallel for schedule(dynamic)
. Баланс нагрузки не оптимален при использовании расписания по умолчанию, потому что чем больше p
, тем меньше рабочая нагрузка.
Ваш код имеет состояние гонки, которое является неопределенным поведением на языке C.
I saw that atomic operation did not have any effect on the code. I got same result with them without them.
Пожалуйста, поймите, что даже если вы получаете правильные результаты для данного компилятора/архитектуры (например, x86/64), это не обязательно означает, что ваш код правильный. Ваш код должен работать правильно (и как задумано) с использованием любых компиляторов/компьютерных архитектур.
term=100000000;
Thread 1, Elapsed time = 6.903768e-01 seconds
Thread 8, Elapsed time = 2.813646e-01 seconds
Я получил ссылку на неопределенную ошибку `omp_set_num_thread". Я изменил свой код в разделе вопросов.
int thread_count = omp_get_num_threads();
Всегда 1, потому что вызывается из последовательной части программы. openmp.org/spec-html/5.0/openmpsu111.htmlЯ изменил код, как вы предложили, но получил ошибку undefined reference to
omp_get_num_procs`. Не могли бы вы внести изменения в мой блок кода, чтобы я мог запустить его без ошибок.
Ваш код компилируется без ошибок в Проводник компилятора. Обратите внимание, что по умолчанию используются все доступные темы, поэтому вы можете пропустить эти строки procs = omp_get_num_procs(); omp_set_num_threads(procs);
.
Почему вы удалили атомарные операции (см. мой предыдущий ответ здесь)? Как установить количество потоков?