Как заставить GNU GCC оптимизировать потоки OpenMP аналогично
Это мой первый пост здесь. Ура! Вернуться к проблеме:
Я учусь использовать OpenMP. Моя IDE - это Code::Blocks. Я хочу улучшить некоторые из моих старых программ. Я должен быть уверен, что результаты будут точно такими же. Похоже, что циклы for оптимизируются в главном потоке иначе, чем в других потоках.
Пример:
#include <iostream>
#include <omp.h>
int main()
{
std::cout.precision(17);
#pragma omp parallel for schedule(static, 1) ordered
for(int i=0; i<4; i++)
{
double sum = 0.;
for(int j=0; j<10; j++)
{
sum += 10.1;
}
#pragma omp ordered
std::cout << "thread " << omp_get_thread_num() << " says " << sum << "\n";
}
return 0;
}
производит
thread 0 says 101
thread 1 says 100.99999999999998579
thread 2 says 100.99999999999998579
thread 3 says 100.99999999999998579
Можно ли каким-то образом убедиться, что все потоки получают такую же оптимизацию, как мои однопоточные программы (которые не использовали OpenMP)?
РЕДАКТИРОВАТЬ:
Компилятор - это "отладчик компилятора и GDB из TDM-GCC (версия 4.9.2, 32-битная, SJLJ)", что бы это ни значило. Это IDE "по умолчанию". Я не знаком с различиями компилятора.
Выходные данные получены из сборки Release, которая добавляет аргумент "-O2".
Ни один из аргументов "-O", "-O1" и "-O3" не выдает "101".
Вы можете попробовать мой.exe из Dropbox (ZIP-файл, также содержит, возможно, необходимые DLL-файлы).
2 ответа
Это происходит из-за того, что тип данных с плавающей запятой или двойной тип данных не может представлять некоторые числа, например 20,2.
#include <iostream>
int main()
{
std::cout.precision(17);
double a=20.2;
std::cout << a << std::endl;
return 0;
}
его вывод будет
20.199999999999999
для получения дополнительной информации об этом см. неожиданный вывод при добавлении двух чисел с плавающей точкой
Не знаю, почему этого не происходит с первым потоком, но если вы удалите openMP, то тоже получите тот же результат.
Из того, что я получаю, это просто численная точность. Для типа с двойным значением следует ожидать точности 16 цифр.
Т.е. результат 101 +/- 1.e-16*101
Это именно тот диапазон, который вы получите. И если вы не используете что-то вроде четверной точности, это так же хорошо, как и получается.