У меня есть эта программа, которая не компилируется из-за error: condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', '>=', or '!=') of loop variable 'i'
, ссылаясь на for (size_t i = 2; i * i <= n; i++)
. Как я могу изменить и исправить это, не влияя на производительность? Это проблема из-за старой версии OpenMP? (Потому что я помню, что раньше у меня была другая проблема на другом компьютере с более старой версией, которая теперь решена.)
#include <iostream>
#include <cstdio>
int main(int argc, char **argv)
{
if (argc != 2)
return EXIT_FAILURE;
size_t n;
if (sscanf(argv[1], "%zu", &n) == 0)
return EXIT_FAILURE;
auto *prime = new size_t[n + 1];
for (size_t i = 2; i <= n; i++)
prime[i] = i;
#pragma omp parallel for
for (size_t i = 2; i * i <= n; i++)
for (size_t j = i * i; j <= n; j += i)
prime[j] = 0;
size_t N = 0;
for (size_t i = 2; i <= n; i++)
if (prime[i] != 0)
N++;
std::cout << N << '\n';
}
Обратите внимание, что в вашем алгоритме есть условие гонки: prime[j]
нельзя безопасно писать параллельно. Доступ должен быть либо атомарным, либо защищенным блокировкой (что делает его медленнее, но это цена за правильный код).
Я заметил, что это плохо распараллеливается. Тут ничего страшного, просто тест, параллельная версия этого алгоритма работает качественно иначе.
Цикл после #pragma omp parallel for
должен быть каноническая форма для подтверждения. В вашем случае проблема связана с тестовым выражением, которое должно быть одним из следующих:
var relational-op b
b relational-op var
Итак, вы должны использовать то, что было предложено @Yakk: вычислить sqrt
из n
и сравнить его с i
:
const size_t max_i=sqrt(n);
#pragma omp parallel for
for (size_t i = 2; i <= max_i; i++)
....
Взять sqrt один раз?