Как заставить 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

Это именно тот диапазон, который вы получите. И если вы не используете что-то вроде четверной точности, это так же хорошо, как и получается.

Другие вопросы по тегам