Russian Qt Forum
Июнь 01, 2024, 20:32 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 2 [3] 4   Вниз
  Печать  
Автор Тема: Как в Qt Creator включить поддержку OpenMP?  (Прочитано 62302 раз)
SABROG
Гость
« Ответ #30 : Март 18, 2010, 13:14 »

На сколько я знаю, то существуют варианты quicksort без рекурсии. В OpenMP используется рекурсивный вариант? Можно поискать реализацию без рекурсии и реализовать её в QtConcurrent, потом сравнить скорости рекурсивного варианта OpenMP и не рекурсивного в QtConcurrent.
Записан
SABROG
Гость
« Ответ #31 : Март 18, 2010, 21:26 »

Судя по статье с сайта microsoft можно сделать следующие выводы. Реализация быстрой сортировки таким методом:

Код
C++ (Qt)
void QuickSort (int numList[],  int nLower, int nUpper)
  {
  if (nLower < nUpper)    
     {
     // create partitions
     int nSplit = Partition (numList, nLower, nUpper);
     #pragma omp parallel sections
     {
        #pragma omp section
        QuickSort (numList, nLower, nSplit - 1);
 
        #pragma omp section
        QuickSort (numList, nSplit + 1, nUpper);
     }
  }
}
 
 

создает 2 конкурентных потока. Это значит, что на машине с 8 ядрами задействованы будут только 2 из них. Разделение массива на 2 части это особенность алгоритма. Но есть еще вариант, который называется 3-way partition. Тут уже будет не один pivot (стержень, опорная точка), а 2. Теоретически можно сделать количество опорных точек равное количеству ядер минус 1. Естественно выгода будет только если массив большой длины. Задействовать 8 ядер для сортировки 16 элементов массива не рационально.

Тут поправьте меня, если я не прав. Первый вызов QuickSort() выполняется на одном ядре в том же потоке в котором и был запущен. Функция Partition() также выполняется на одном ядре. Разделение на конкурентные потоки происходит только после того как Partition() разделит массив на 2 части. С левой стороны числа меньшие или равные опорному значению, с правой стороны числа большие опорного значению. Тут происходит первый рекурсивный вызов, а точнее 2 вызова QuickSort, что аналогично запуску двух новых потоков. Дальнейшие рекурсивные вызовы происходят внутри независимых потоков. Я например не вижу никаких припятствий рекурсивного вызова функции находящейся в отдельном потоке. Почему бы для QtConcurrent это стало проблемой? Думаю проблем тут никаких нет.

Хороший плюс в пользу OpenMP это возможность переключение на стандартный алгоритм сортировки при отсутствии библиотеки OpenMP. То есть не нужно переписывать старый код. С вариантом использования QtConcurrent нужно делать рефакторинг.

Задачи, которые хотелось бы решить:
- реализовать X-Way partition алгоритм (как бы авторские права на патент не нарушить), где X количество процессоров минус один.
- реализовать алгоритм поиска медианы в качестве опорного значения, чтобы распределить нагрузку на ядра и увеличить скорость сортировки. В стандартном варианте берется самый первый элемент массива в качестве опорного значения. Это означает, что из двух частей (левой и правой) одна часть может содержать 2 элемента, в то время как другая тысячу. Естественно, что при таком раскладе большую часть работы будет делать только одно ядро.
- переписать алгоритм, чтобы полностью отказаться от рекурсии. В худшем случае ограничить максимальную глубину рекурсии (level).

Какой бы алгоритм сортировки не был хороший все зависит от данных, которые будут располагаться в массиве. В самом худшем случае будет работать только одно ядро.
---
Нашел безрекурсивный вариант, основанный только на вложенных циклах:

Код
C++ (Qt)
//  quickSort
//
//  This public-domain C implementation by Darel Rex Finley.
//
//  * This function assumes it is called with valid parameters.
//
//  * Example calls:
//    quickSort(&myArray[0],5); // sorts elements 0, 1, 2, 3, and 4
//    quickSort(&myArray[3],5); // sorts elements 3, 4, 5, 6, and 7
 
#define MAX_LEVELS 300
 
void quickSort(int* arr, int elements)
{
   int piv;
   int beg[MAX_LEVELS];
   int end[MAX_LEVELS];
   int i = 0;
   int L;
   int R;
   int swap;
 
   beg[0] = 0;
   end[0] = elements;
 
   while (i >= 0) {
       L = beg[i];
       R = end[i]-1;
 
       if (L < R) {
           piv = arr[L];
           while (L < R) {
               while (arr[R] >= piv && L < R)
                   R--;
               if (L < R)
                   arr[L++] = arr[R];
 
               while (arr[L] <= piv && L < R)
                   L++;
               if (L < R)
                   arr[R--] = arr[L];
           }
 
           arr[L] = piv;
           beg[i+1] = L+1;
           end[i+1] = end[i];
           end[i++] = L;
 
           if (end[i]-beg[i] > end[i-1]-beg[i-1]) {
               swap = beg[i];
               beg[i] = beg[i-1];
               beg[i-1] = swap;
               swap = end[i];
               end[i] = end[i-1];
               end[i-1] = swap;
           }
       }
       else {
           i--;
       }
   }
}
 
 

Только его похоже придется переписывать, я пока не разобрался полностью в этой реализации и возможно ли будет её распараллелить.
« Последнее редактирование: Март 18, 2010, 22:20 от SABROG » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #32 : Март 18, 2010, 22:28 »

Мне нужна была балансировка kd-дерева, я скопировал по примеру QuickSort, откуда - не помню  Улыбающийся Вот др. простой пример, техника та же самая http://www.openmp.org/pipermail/omp/2005/000145.html

Все процессоры могут быть задействованы хотя да, нагрузка не перераспределяется. Да, первое деление выполняется на 1 ядре (в главной нитке), потом на 2-х рабочих нитках и.т.д. Разумно (и нужно) ограничить числом ядер.

Дальнейшие рекурсивные вызовы происходят внутри независимых потоков. Я например не вижу никаких припятствий рекурсивного вызова функции находящейся в отдельном потоке. Почему бы для QtConcurrent это стало проблемой? Думаю проблем тут никаких нет.
Тут я Вас не понял. Ф-ции это просто код, одна и та же ф-ция может одновременно выполняться в разных нитках. "Задействовать" одну нитку из другой совсем не просто - надо как-то ей "дать задачу", ведь просто вызвать ф-цию - ну она в вызванной нитке и выполнится. Директивы task/taskq это делают, пусть нужна обвязка но это вполне приемлемо. Вместо этого брать следующую нитку из пула - резона нет, больше потеряется на запуске/останове.

Нашел безрекурсивный вариант, основанный только на вложенных циклах:
...
Только его похоже придется переписывать, я пока не разобрался полностью в этой реализации и возможно ли будет её распараллелить.
Так вот именно, альтернативный алгоритм - удовольствие дорогое
Записан
SABROG
Гость
« Ответ #33 : Март 18, 2010, 23:33 »

Чего-то мы тут велосипед придумываем. Оказывается достаточно подключить openmp к программе и большинство стандартных алгоритмов начинают сами распараллеливаться: http://gcc.gnu.org/onlinedocs/libstdc++/manual/bk01pt12ch31s03.html

Только еще надо дефайн передать -D_GLIBCXX_PARALLEL и использовать другое наименование методов, "__gnu_parallel::sort" например.

P.S.: проголосовал за предложение сделать распараллеленные версии алгоритмов Qt.

P.P.S.: прикольный ролик-визуализатор двух алгоритмов Buble Sort и Quick Sort. Роботы сортируют Улыбающийся

P.P.P.S: оказывается сортировка Radix быстрее на GPU, чем QuickSort.
« Последнее редактирование: Март 19, 2010, 20:30 от SABROG » Записан
maxwellcut
Гость
« Ответ #34 : Март 23, 2010, 23:28 »

Послушайте, кто-нибудь сталкивался с подобной задачей? В общем нужно реализовать параллельную задачу через OpenMp. Данные вводятся с формы, далее запускается рассчеты, при этом форма во время этих рассчетов не должна тормозить. Если просто написать подряд код на OpenMP, то форма виснет пока все это не посчитается. Если создать еще один поток QThread и кинуть ему данные на обсчет с помощью OpenMP, то почему-то функции OpenMP перестают работать, точнее при вызове функции из потока вылетает исключение, что "Инструкция обратилась по адресу //=//=//=, память не может быть 'read'". Обычно такое возникает при одновременном доступе потоков к одному ресурсу, но у меня инструкции OpenMP используются только в одном потоке. Использование QMutex перед вызовом OpenMPшных функций не помогает. Я был бы рад услышать ваши соображения по данной проблеме, заранее благодарю.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #35 : Март 24, 2010, 11:35 »

Послушайте, кто-нибудь сталкивался с подобной задачей? В общем нужно реализовать параллельную задачу через OpenMp. Данные вводятся с формы, далее запускается рассчеты, при этом форма во время этих рассчетов не должна тормозить. Если просто написать подряд код на OpenMP, то форма виснет пока все это не посчитается. Если создать еще один поток QThread и кинуть ему данные на обсчет с помощью OpenMP, то почему-то функции OpenMP перестают работать, точнее при вызове функции из потока вылетает исключение, что "Инструкция обратилась по адресу //=//=//=, память не может быть 'read'". Обычно такое возникает при одновременном доступе потоков к одному ресурсу, но у меня инструкции OpenMP используются только в одном потоке. Использование QMutex перед вызовом OpenMPшных функций не помогает. Я был бы рад услышать ваши соображения по данной проблеме, заранее благодарю.
1)  Нитка из которой запускаются праллельные вычисления сама также считает, не нужно надеяться что она, мол, стоит и ждет.

2) Почему не работает из др. нитки - не знаю, может проблема не связана с OpenMP, нужно "потренироваться на кошках"

3) Простое решение вставить в расчеты

Код:
#pragma omp master
ProcessEvents();          // будет выполняться в главном потоке
Записан
AlekseyK
Гость
« Ответ #36 : Май 06, 2010, 16:08 »

Все, спасибо всем, кто уделил мне время и помог разобраться. У меня все заработало

Просветите, пожалуйста, как?! Как удалось избавиться от Sementeation Fault?
Записан
AlekseyK
Гость
« Ответ #37 : Май 06, 2010, 16:52 »

Если будет выпадать с segmentation fault, это известный баг в gcc, описание тут:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42616
Пока что не исправлено Грустный(

А известно, когда исправят? Там предложен патч для openmp, но пока не представляю как его применить и пересобрать под винду: openmp идёт же вместе с mingw?
Записан
kdm
Гость
« Ответ #38 : Май 09, 2010, 10:42 »

Здесь был поднят вопрос о том, что в gcc есть баг (пока еще неисправленный), который встречается при работе с OpenMP. На него я как раз наткнулся. А другой пользователь в самом начале говорил, что в VC2008 все нормально работает. И хотел бы спросить, как работать с Qt в вместе с VC, то есть что нужно скачать, прописать, настроить? Ничего этого, я увы не знаю, а делать задание нужно. Может что присоветуете. А, а под линуксом с gcc такая же проблемма?
« Последнее редактирование: Май 09, 2010, 10:56 от kdm » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #39 : Май 09, 2010, 12:44 »

Здесь был поднят вопрос о том, что в gcc есть баг (пока еще неисправленный), который встречается при работе с OpenMP. На него я как раз наткнулся. А другой пользователь в самом начале говорил, что в VC2008 все нормально работает. И хотел бы спросить, как работать с Qt в вместе с VC, то есть что нужно скачать, прописать, настроить? Ничего этого, я увы не знаю, а делать задание нужно. Может что присоветуете. А, а под линуксом с gcc такая же проблемма?
Мне предстоит перетаскивать на Вындоуз, но через 1-2 месяца. На OSX все работает как доктор прописал, на gcc (даже 4.2), так и на Intel компиляторах. Срастается с Qt без проблем. В любом случае кроме библиотеки и хедера (omp.h)  нужна установка компиляции -fopenmp, я задаю это в IDE, должно иметь тот же эффект в командной строке.
Записан
AlekseyK
Гость
« Ответ #40 : Май 11, 2010, 12:07 »

Здесь был поднят вопрос о том, что в gcc есть баг (пока еще неисправленный), который встречается при работе с OpenMP. На него я как раз наткнулся. А другой пользователь в самом начале говорил, что в VC2008 все нормально работает. И хотел бы спросить, как работать с Qt в вместе с VC, то есть что нужно скачать, прописать, настроить? Ничего этого, я увы не знаю, а делать задание нужно. Может что присоветуете. А, а под линуксом с gcc такая же проблемма?

Я скачал это: http://ftp://ftp.qt.nokia.com/qt/source/qt-win-opensource-4.6.2-vs2008.exe - по идее само собирается, но ещё не пробовал. Ну и Visual Studio Add-in (44 MB) наверное нужен, если в VS писать, собирать: http://qt.nokia.com/downloads
Записан
AlekseyK
Гость
« Ответ #41 : Май 11, 2010, 12:51 »

Поставил, попробовал: пока не собирается из-за отличий g++ и ms C++. Как включать OpenMP в VS есть здесь: http://msdn.microsoft.com/en-us/library/fw509c3b(v=VS.80).aspx, однако неизвестно, есть ли этот функционал в VS Express версии.
Записан
AlekseyK
Гость
« Ответ #42 : Май 12, 2010, 12:07 »

У меня собралось под VC++ и работает. Что интересно: скорость в debug версии у g++ и VC++ примерно одинаковая, интересно будет с оптимизацией проверить. OpenMP в VS работает прекрасно, в отличии от MinGW, однако медленнее, чем без OpenMP: видимо я лишнего распараллелил - много накладных расходов, будем убирать лишнее.
Записан
AlekseyK
Гость
« Ответ #43 : Май 12, 2010, 17:26 »

Что интересно: для моей программы (много циклов и вычислений) gcc сгенерировал примерно на 25% более быстрый код, чем Visual C++. Это с O2 - почти в равных условиях так сказать (у gcc был march=athlon-xp, у MS аналогичной опции не нашёл - видимо её и нет). При O3 и всех опциях оптимизации в MS соотношение примерно то же - на 22% gcc быстрее, и собранная g++ программа работает чуть медленнее, MS - немного быстрее.
Записан
AlekseyK
Гость
« Ответ #44 : Май 12, 2010, 17:44 »

Я рад Улыбающийся

На самом деле можно сократить до
"QMAKE_LIBS+=-static -lgomp -lpthread" "QMAKE_CXXFLAGS+=-fopenmp"

Если будет выпадать с segmentation fault, это известный баг в gcc, описание тут:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42616
Пока что не исправлено Грустный(

TDM's GCC/MinGW32 тоже извещена об этой проблеме:
http://sourceforge.net/tracker/?func=detail&aid=2921774&group_id=200665&atid=974439
Записан
Страниц: 1 2 [3] 4   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.096 секунд. Запросов: 20.