На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела Visual C++ / MFC / WTL (далее Раздела)
1) На Раздел распространяются все Правила Форума.
2) Перед тем, как создать новый топик, убедитесь, что Вы читали Правила создания тем в Разделе.
3) Вопросы, не связанные с программированием (настройки MS Visual Studio, книги, библиотеки и т.д.),
обсуждаются в разделе C/C++: Прочее
4) Вопросы разработки .NET (Windows Form, C++/CLI и т.п.) приложений на Visual C++/C# обсуждаются в разделе .NET.
5) Нарушение Правил может повлечь наказание со стороны модераторов.

Полезные ссылки:
user posted image FAQ Раздела user posted image Обновления для FAQ Раздела user posted image Поиск по Разделу user posted image MSDN Library Online
Модераторы: ElcnU
Страницы: (3) [1] 2 3  все  ( Перейти к последнему сообщению )  
> Почему не работает OpenMP?
    Сделал 2 функции без использования и с ипользованием OpenMP
    ExpandedWrap disabled
      #include <string>
      #include <iostream>
      #include <fstream>
      #include <Windows.h>
      #include <omp.h>
       
      using namespace std;
       
      struct Result
      {
        LARGE_INTEGER StopTime, StopTimeNthread, Freq, StartTime, StartTimeNthread;
        long nRes, nResNthread;
        int nthread;
      };
       
      Result res;
       
      ofstream fTest;
       
      void sum_arr(const long n) // обычная функция
      {
        long sum = 0;
        long* a = (long*)malloc(sizeof(long)*n);
        for(long i = 0; i < n; ++i)
        {
          a[i] = 1;
        }
        QueryPerformanceCounter(&res.StartTime);
        for(long i = 0; i < n; ++i)
        {
          sum += a[i];
        }
        QueryPerformanceCounter(&res.StopTime);
        res.nRes = sum;
        free(a);
      }
       
      void sum_arr_omp(const long n) // обычная функция
      {
        long sum = 0;
        long* a = (long*)malloc(sizeof(long)*n);
        for(long i = 0; i < n; ++i)
        {
          a[i] = 1;
        }
        res.nthread = omp_get_max_threads();
        QueryPerformanceCounter(&res.StartTimeNthread);
        #pragma omp parallel shared(a) reduction (+: sum) num_threads(res.nthread)
        {
         #pragma omp for    
         for(long i = 0; i < n; ++i)
         {
           sum += a[i];
         }
        } // #pragma omp parallel
        QueryPerformanceCounter(&res.StopTimeNthread);
        res.nResNthread = sum;
        free(a);
      }
       
      int main()
      {
        setlocale(LC_ALL, "");
        double nMax;
        QueryPerformanceFrequency(&res.Freq);
        fTest.open("Test.txt", ios::app | ios::out | ios::binary);
        sum_arr(1000000);
        sum_arr_omp(1000000);
        nMax = ((double)res.StopTime.QuadPart - (double)res.StartTime.QuadPart)/((double)res.StopTimeNthread.QuadPart
              - (double)res.StartTimeNthread.QuadPart);
        cout  << nMax << "\t\tefficiency of use " <<  res.nthread << " threads"  << endl;
        fTest << nMax << "\t\tefficiency of use " <<  res.nthread << " threads"  << endl;
        if(res.nRes != res.nResNthread)
          cout << "!!! Error" << endl;
        system("\npause");
        return 0;
      }
    Однако использование OpenMP не дает выигрыша по времени, а даже замедляет выполнение программы. Помогите, пожалуйста, разобраться. Проект прикрепил
    Прикреплённый файлПрикреплённый файлCpuGpu.zip (2,42 Кбайт, скачиваний: 91)
      Цитата tuchin @
      Однако использование OpenMP не дает выигрыша по времени, а даже замедляет выполнение программы. Помогите, пожалуйста, разобраться. Проект прикрепил

      Скорее всего просто погрешность, на таких операциях. Отключи оптимизацию в компиляторе. Ну и сделай там какие-нибудь операции потяжелее.
        Оптимизации в проекте нет. Сделал умножение векторов - тот же результат. Отношение времени без OpenMP и с OpenMP изменяется в пределах от 0.5 до 1.5 при запусках программы
          Показанный код ограничивается не вычислительной мощностью, а скоростью обращения к памяти. При работе многих потоков эти обращения еще и происходят не строго последовательно.
            Проверь, кстати, что твой код работает в разных потоках. А то эти прагмы ни4ого ни к чему необязывают, могут тупо игнорироваться.
              было у нас такое - из-за кеширования распараллеливание только тормозило процесс. типа если каждый поток юзает небольшой кусок памяти для одной итерации, то остальные потоки ждут, пока один поток полностью кэш переберет. как-то так :)
                Цитата Олег М @
                Проверь, кстати, что твой код работает в разных потоках. А то эти прагмы ни4ого ни к чему необязывают, могут тупо игнорироваться.

                А как это проверить?
                  tuchin
                  Вы не учли что на синхронизацию потоков нужно время.
                  Время переключения между потоками порядка 10 мкс. А время реакции OpenMP может быть гораздо выше в плоть до хх мс. За это время основной поток у вас успевает всё просчитать самостоятельно. Увеличьте расчёт в 100 раз по времени.
                  А ещё лучше до 10 секунд. Тогда побочные эффекты с временем на ваш тест не будут влиять.
                  Сообщение отредактировано: Pavia -
                    Посоветуйте, пожалуйста, какую-либо времени затратную операцию, чтобы ее можно было выполнить в потоках и включить в цикл. Тестирую в настоящее время программу на планшете с 2 Гб оперативной памяти, при выделении памяти под большой массив получаю NULL.
                      И на сумме получилось. При nMax = 100000000 выигрыш составил в среднем 2.5 раза
                        Цитата Pavia @
                        Вы не учли что на синхронизацию потоков нужно время.
                        Время переключения между потоками порядка 10 мкс. А время реакции OpenMP может быть гораздо выше в плоть до хх мс. За это время основной поток у вас успевает всё просчитать самостоятельно. Увеличьте расчёт в 100 раз по времени.
                        А ещё лучше до 10 секунд. Тогда побочные эффекты с временем на ваш тест не будут влиять.

                        Спасибо большое за подробный ответ! А как Вы определили, что переключение между потоками занимает около 10 мкс?
                          Цитата Pavia @
                          между потоками порядка 10 мкс

                          скорее порядка 1-10мс
                            tuchin
                            Мне была очень интересна эта тема времени. И я её досконально изучал. Жалко с OpenMP я мало работал.
                            Сейчас запустил ваш тест получил не внятные результаты. Основываясь на опыте увеличил время замера. Гипотетические высказывания совпали с практическими.

                            По поводу цифр это примерные значения, так как с OpenMP я мало работал. Не надо их воспринимать буквально и делать поспешных выводов.
                            Откуда известно, что время переключения задач занимает 10 мкс? Intel приводит информацию для своих процессоров. А также есть презентация от Макрософта с информация о том как работает планировщик в виндоусе.

                            10 мс это короткий цикл, когда переключение известно кого на кого.
                            1-10 мс это время выгрузки регистров ядра в КЭШ в зависимости от модели процессора. А переключение это выгрузка плюс загрузка умножаем на 2. И плюс энергосберегающий режим, так как Интела приводит для максимальной частоты. А это ещё умножь на 3 раза.
                              Вообще, подразумевается, что потоки работают на разных процессорах. Поэтому переключения контекста не должно так сильно влиять на результат по сравнению с одним потоком.
                                В данном случае дело не просто в переключении контекста, а в создании и инициализации новых потоков (как объектов ядра ОС) и, главное, в возможной задержке их запуска, т.к. созданные потоки запускаются не сразу, а просто ставятся в очередь планировщика потоков (соответствующего приоритета). Отсюда и плавание результатов от выигрыша до проигрыша в зависимости от того, сколько сторонних потоков (с тем же или более высоким приоритетом) исполняется или находится в очереди в данный момент, и через какое время они добровольно или принудительно отдадут управление планировщику. Причем для получения существенного проигрыша (при малом общем времени исполнения) достаточно, чтобы запуск хотя бы одного из вновь созданных потоков был задержан на существенное время.

                                Резюме: Более и или менее стабильный выигрыш от многопоточности можно получить только на интервалах времени, значительно превышающих квант переключения потоков в ОС (т.е. >> 10-15 мс). Если все же хочется "поиграться" с OpenMP на интервалах, сравнимых с квантом, то лучше не "жадничать" и задавать кол-во потоков меньше max_threads в расчете на то, что один или несколько логических процессоров м.б. заняты другими потоками\задачами.
                                Сообщение отредактировано: leo -
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (3) [1] 2 3  все


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0364 ]   [ 19 queries used ]   [ Generated: 24.04.24, 23:07 GMT ]