Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.14.142.115] |
|
Страницы: (3) [1] 2 3 все ( Перейти к последнему сообщению ) |
Сообщ.
#1
,
|
|
|
Сделал 2 функции без использования и с ипользованием OpenMP
#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; } Прикреплённый файлCpuGpu.zip (2,42 Кбайт, скачиваний: 91) |
Сообщ.
#2
,
|
|
|
Цитата tuchin @ Однако использование OpenMP не дает выигрыша по времени, а даже замедляет выполнение программы. Помогите, пожалуйста, разобраться. Проект прикрепил Скорее всего просто погрешность, на таких операциях. Отключи оптимизацию в компиляторе. Ну и сделай там какие-нибудь операции потяжелее. |
Сообщ.
#3
,
|
|
|
Оптимизации в проекте нет. Сделал умножение векторов - тот же результат. Отношение времени без OpenMP и с OpenMP изменяется в пределах от 0.5 до 1.5 при запусках программы
|
Сообщ.
#4
,
|
|
|
Показанный код ограничивается не вычислительной мощностью, а скоростью обращения к памяти. При работе многих потоков эти обращения еще и происходят не строго последовательно.
|
Сообщ.
#5
,
|
|
|
Проверь, кстати, что твой код работает в разных потоках. А то эти прагмы ни4ого ни к чему необязывают, могут тупо игнорироваться.
|
Сообщ.
#6
,
|
|
|
было у нас такое - из-за кеширования распараллеливание только тормозило процесс. типа если каждый поток юзает небольшой кусок памяти для одной итерации, то остальные потоки ждут, пока один поток полностью кэш переберет. как-то так
|
Сообщ.
#7
,
|
|
|
Цитата Олег М @ Проверь, кстати, что твой код работает в разных потоках. А то эти прагмы ни4ого ни к чему необязывают, могут тупо игнорироваться. А как это проверить? |
Сообщ.
#8
,
|
|
|
tuchin
Вы не учли что на синхронизацию потоков нужно время. Время переключения между потоками порядка 10 мкс. А время реакции OpenMP может быть гораздо выше в плоть до хх мс. За это время основной поток у вас успевает всё просчитать самостоятельно. Увеличьте расчёт в 100 раз по времени. А ещё лучше до 10 секунд. Тогда побочные эффекты с временем на ваш тест не будут влиять. |
Сообщ.
#9
,
|
|
|
Посоветуйте, пожалуйста, какую-либо времени затратную операцию, чтобы ее можно было выполнить в потоках и включить в цикл. Тестирую в настоящее время программу на планшете с 2 Гб оперативной памяти, при выделении памяти под большой массив получаю NULL.
|
Сообщ.
#10
,
|
|
|
И на сумме получилось. При nMax = 100000000 выигрыш составил в среднем 2.5 раза
|
Сообщ.
#11
,
|
|
|
Цитата Pavia @ Вы не учли что на синхронизацию потоков нужно время. Время переключения между потоками порядка 10 мкс. А время реакции OpenMP может быть гораздо выше в плоть до хх мс. За это время основной поток у вас успевает всё просчитать самостоятельно. Увеличьте расчёт в 100 раз по времени. А ещё лучше до 10 секунд. Тогда побочные эффекты с временем на ваш тест не будут влиять. Спасибо большое за подробный ответ! А как Вы определили, что переключение между потоками занимает около 10 мкс? |
Сообщ.
#12
,
|
|
|
Цитата Pavia @ между потоками порядка 10 мкс скорее порядка 1-10мс |
Сообщ.
#13
,
|
|
|
tuchin
Мне была очень интересна эта тема времени. И я её досконально изучал. Жалко с OpenMP я мало работал. Сейчас запустил ваш тест получил не внятные результаты. Основываясь на опыте увеличил время замера. Гипотетические высказывания совпали с практическими. По поводу цифр это примерные значения, так как с OpenMP я мало работал. Не надо их воспринимать буквально и делать поспешных выводов. Откуда известно, что время переключения задач занимает 10 мкс? Intel приводит информацию для своих процессоров. А также есть презентация от Макрософта с информация о том как работает планировщик в виндоусе. 10 мс это короткий цикл, когда переключение известно кого на кого. 1-10 мс это время выгрузки регистров ядра в КЭШ в зависимости от модели процессора. А переключение это выгрузка плюс загрузка умножаем на 2. И плюс энергосберегающий режим, так как Интела приводит для максимальной частоты. А это ещё умножь на 3 раза. |
Сообщ.
#14
,
|
|
|
Вообще, подразумевается, что потоки работают на разных процессорах. Поэтому переключения контекста не должно так сильно влиять на результат по сравнению с одним потоком.
|
Сообщ.
#15
,
|
|
|
В данном случае дело не просто в переключении контекста, а в создании и инициализации новых потоков (как объектов ядра ОС) и, главное, в возможной задержке их запуска, т.к. созданные потоки запускаются не сразу, а просто ставятся в очередь планировщика потоков (соответствующего приоритета). Отсюда и плавание результатов от выигрыша до проигрыша в зависимости от того, сколько сторонних потоков (с тем же или более высоким приоритетом) исполняется или находится в очереди в данный момент, и через какое время они добровольно или принудительно отдадут управление планировщику. Причем для получения существенного проигрыша (при малом общем времени исполнения) достаточно, чтобы запуск хотя бы одного из вновь созданных потоков был задержан на существенное время.
Резюме: Более и или менее стабильный выигрыш от многопоточности можно получить только на интервалах времени, значительно превышающих квант переключения потоков в ОС (т.е. >> 10-15 мс). Если все же хочется "поиграться" с OpenMP на интервалах, сравнимых с квантом, то лучше не "жадничать" и задавать кол-во потоков меньше max_threads в расчете на то, что один или несколько логических процессоров м.б. заняты другими потоками\задачами. |