На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Обратите внимание:
1. Прежде чем начать новую тему или отправить сообщение, убедитесь, что вы не нарушаете правил форума!
2. Обязательно воспользуйтесь поиском. Возможно, Ваш вопрос уже обсуждали. Полезные ссылки приведены ниже.
3. Темы с просьбой выполнить какую-либо работу за автора в этом разделе не обсуждаются.
4. Используйте теги [ code=cpp ] ...текст программы... [ /code ] для выделения текста программы подсветкой.
5. Помните, здесь телепатов нет. Старайтесь формулировать свой вопрос максимально грамотно и чётко: Как правильно задавать вопросы
6. Запрещено отвечать в темы месячной и более давности без веских на то причин.

Полезные ссылки:
user posted image FAQ Сайта (C++) user posted image FAQ Форума user posted image Наши Исходники user posted image Поиск по Разделу user posted image MSDN Library Online (Windows Driver Kit) user posted image Google

Ваше мнение о модераторах: user posted image B.V.
Модераторы: B.V.
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> Использование OpenMP
    Пытаюсь научиться многоядерному программированию. Начал с OpenMP. Нашел пример подсчета суммы элементов массива. Сравнил обычную функцию и функцию с использованием OpenMP, оказалось, что наибольший эффект от использования OpenMP достигается тогда, когда в инструкции
    ExpandedWrap disabled
      #pragma omp parallel shared(a) reduction (+: sum) num_threads(4)
    я указываю в num_threads(4) количество логических процессоров (у меня 2 ядра и 4 логических процессора по данным монитора ресурсов в Windows7. Возникли следующие вопросы:
    1. С помощью каких функций API можно определить количество логических процессоров?
    2. На ПК с другим количеством логических процессоров нужно указывать другое число. Можно ли в директиве #pragma менять это число или нужно после определения количества логических процессоров делать switch на возможные значения и устанавливать в директиве pragma количество процессоров в ветвях switch?
      Посмотри
      omp_get_max_threads
      omp_set_num_threads
        Спасибо за подсказку. omp_get_max_threads()=4 на моем ПК, т.е. равно числу логических процессоров. Но если сделать так:
        ExpandedWrap disabled
            omp_set_num_threads(16);
            cout << "Максимальное количество потoков: " << omp_get_max_threads() << endl;
        то omp_get_max_threads() покажет 16. Получается, что без специальной установки количества процессов максимальное количество процессов равно количеству логических процессоров. Попробую попробовать на разных ПК. О результатах сообщу.
          Ещё есть omp_get_num_procs

          Добавлено
          https://msdn.microsoft.com/en-us/library/k1h4zbed.aspx
            omp_get_num_procs() дает 4, наверное это лучшее решение
              А по второму вопросу? В прагме нельзя менять число, нужно использовать switch после определения числа логических процессоров?
                Цитата tuchin @
                А по второму вопросу? В прагме нельзя менять число, нужно использовать switch после определения числа логических процессоров?

                #pragma - это compile-time. Тебе же нужен runtime
                Просто вызови эти функции перед прагмой. Что-то типа
                ExpandedWrap disabled
                  omp_set_num_threads(omp_get_num_procs())
                  #pragma omp parallel
                  Спасибо, понятно

                  Добавлено
                  Хотел бы еще спросить о том, как правильно определять выигрыш при использовании OpenMP. В программе
                  ExpandedWrap disabled
                    #include <string>
                    #include <iostream>
                    #include <Windows.h>
                    #include <memory.h>
                    #include <stdio.h>
                    #include <time.h>
                    #include <omp.h>
                     
                    using namespace std;
                     
                    double sum_arr(double* a, const long long n) // обычная функция
                    {
                      double sum = 0.0;
                      for(int i = 0; i < n; ++i)
                      {
                        sum += a[i];
                      }
                      return sum;
                    }
                     
                    double sum_arr_openmp(double* a, const long long n)
                    {
                      double sum = 0.0;
                      omp_set_num_threads(omp_get_num_procs());
                      #pragma omp parallel shared(a) reduction (+: sum)
                      {
                        #pragma omp for
                        for (long long i = 0; i < n; ++i)
                        {
                          sum += a[i];
                        }
                      }
                      return sum;
                    }
                     
                    int main()
                    {
                      setlocale(LC_ALL, "");
                      clock_t start, finish;
                      omp_set_num_threads(16);
                      cout << "Максимальное количество threads: " << omp_get_max_threads() << endl;
                      cout << "Количество procs: " << omp_get_num_procs() << endl;
                      long long n = 100000000;
                      double* a = (double*)malloc(sizeof(double)*n);
                      for(long long i = 0; i < n; ++i)
                      {
                        a[i] = i;
                      }
                      start = clock();
                      double sum = sum_arr(a, n);
                      finish = clock();
                      double duration = (double)(finish - start);
                      cout << "Сумма = " << sum << ". Время расчета без OpenMP = " << duration << endl;
                      start = clock();
                      sum = sum_arr_openmp(a, n);
                      finish = clock();
                      duration = (double)(finish - start);
                      cout << "Сумма = " << sum << ". Время расчета  c  OpenMP = " << duration << endl;
                      free(a);
                      system("\npause");
                    }
                  все время при каждом запуске получаются разные результаты. Я использую Visual Studio 2010 в Windows 7, может быть в IDE есть какие-либо встроенные средства оценки быстродействия функций? Наверное, оценка быстродействия через clock - не самый лучший способ.
                    запускайте несколько сотен раз подряд и усредняйте результат
                      Цитата tuchin @
                      все время при каждом запуске получаются разные результаты


                      Разные, это какие? Что именно там не так?
                      Кстати, а почему ты пользуешися именно omp, а не обычными потоками?
                        Вообще, я бы для начала убедился, что цикл, который у тебя выполняется в sum_arr_openmp выполняется параллельно, берёт нужный диапазон, и ничего лишний раз не блокирует.
                        Я нифига не понимаю в omp, но в этой задаче сделал бы, чтоб каждый поток считал свою сумму, а потом, по выходу из цикла, прибавлял её к общей.
                        Здесь же выглядит так, что есть общая переменная sum, которая блокируется каждым потоком, в каждой итерации. В этом случае результат далеко не однозначен.
                          Цитата tuchin @
                          все время при каждом запуске получаются разные результаты

                          Ну естественно разные, у тебя классическая гонка потоков (race condition на буржуйском).
                            А как это исправить?

                            Добавлено
                            Цитата Олег М @
                            Разные, это какие? Что именно там не так?
                            Кстати, а почему ты пользуешися именно omp, а не обычными потоками?

                            Потому что многопоточным программированием никогда не занимался, решил, что профессионалы (которые создали OpenMP, OpenCL, C++ AMP) лучше справятся с задачей создания многопоточного программирования, чем новичок.
                              Цитата tuchin @
                              А как это исправить?
                              Ну у меня получилось просто "тупым" более аккуратным распараллеливанием:
                              ExpandedWrap disabled
                                double sum_arr_openmp2(double *a, const long long n)
                                {
                                    double sum = 0.0;
                                    int k;
                                    omp_set_num_threads( k = omp_get_num_procs());
                                    #pragma omp parallel for shared(a,k) reduction (+: sum)
                                    for( int p=0; p<k; p++)
                                    {
                                        double sumP=0.0;// omp_get_thread_num()
                                        long long stopP = (p+1)*n/k;
                                        for( long long i = p*n/k; i < stopP; i++)
                                            sumP += a[i];
                                        sum += sumP;
                                    }
                                 
                                    return sum;
                                }
                              Впрочем, только на x64: 641 147 93
                              А вот на x86 увы: 777 153 175
                              :-?
                                Цитата tuchin @
                                А как это исправить?

                                Убедиться, что два потока никогда не смогут одновременно менять одну и ту же переменную. Использовать либо атомарный инкремент, либо критические секции для этого.
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0785 ]   [ 17 queries used ]   [ Generated: 28.03.24, 10:56 GMT ]