объединение различных подходов к созданию потоков - PullRequest
0 голосов
/ 21 апреля 2011

Я занимаюсь разработкой приложения для оконной формы, которое предназначено для манипулирования изображениями в реальном времени.Пользовательский интерфейс является ключевым элементом, и я хочу использовать многопоточность для выполнения задач обработки изображений отдельно от потока пользовательского интерфейса.Не только это, но и из-за интенсивности вычислений я хочу выполнить обработку изображения в нескольких потоках.

Один из способов, которым мне удалось это сделать, - использовать делегат ThreadStart для обработки нескольких потоков.,Это работает довольно хорошо, но я явно создаю каждый поток.Другой подход, который я рассмотрел, заключается в использовании openMP для выполнения задач обработки в нескольких потоках.OpenMP кажется гораздо более простым подходом, поскольку он автоматически назначает обработку всем доступным потокам.Это было бы особенно полезно, когда программа запускается на разных компьютерах с разным количеством ядер на каждом.Однако я обнаружил, что отзывчивость пользователя недостаточна при подходе openMP, и я пришел к выводу, что это связано с вычислениями, выполняемыми также в потоке пользовательского интерфейса.

Поэтому я попытался объединить два подхода,Я запускаю новый поток, используя поток старта, из которого я вызываю функцию, которая выполняет обработку изображения с использованием openMP для распараллеливания цикла for.Однако, когда я делаю это, программа не использует все доступные ей потоки (кажется, что она использует только 2 или 3 из 8).

Следовательно, у меня следующие вопросы: будет ли это плохой практикойпопытаться сделать многопоточность этими двумя разными способами?Есть ли способ успешно реализовать комбинацию подходов так, чтобы она выполняла обработку изображений во всех доступных потоках, но оставляла поток пользовательского интерфейса для обработки пользовательского ввода?Или, может быть, есть более простая реализация, использующая только один из вышеуказанных подходов?Я понимаю, что, возможно, я мог бы динамически создавать потоки, используя threadstart, но это кажется более сложным подходом, чем если бы я мог вместо этого использовать openMP.

Вот некоторый псевдокод, показывающий, что я хочу сделать (примечание: ProcessedData и ImageDataбеззнаковые массивы данных пикселей):

//this sets up a new thread when called for in the form
public: static void ThreadProc()
{
    ProcessedData=compute(ImageData); //this is the image processing, there are other variable as well as ImageData
};

//this computes the processed image when the user moves a label/node
private: void labelnode_MouseMove( Object^ /*sender*/, System::Windows::Forms::MouseEventArgs^ e ) {
    //if not being moved or left mouse button not used, exit    
    if (!bMoving || e->Button != System::Windows::Forms::MouseButtons::Left)    
    {       
        return; 
    };
    Thread^ oThread = gcnew Thread( gcnew ThreadStart( &Form1::ThreadProc ) );
    oThread->Start(); //launch new thread to do calculations for image processing
};

Функция вычисления содержит следующий параллельный цикл:

#define CHUNKSIZE 1 
#pragma omp parallel 
{
    #pragma omp for schedule(dynamic, CHUNKSIZE)
    for (i=0;i<numberofrows;i++)
    {
        //Process all of the pixels in the given row putting results in the processed data array.
    };
};

ОБНОВЛЕНИЕ: На самом деле оказывается, что средства отладки препятствовали полной производительностиприложения.Запуск exe внешне работает как надо.Тем не менее, теперь у меня есть утечка памяти, которая вызывает сбой после повторения процесса достаточно раз.Я уверен, что не было утечки памяти до того, как я распараллелился с openMP, поэтому мне интересно, осталась ли некоторая остаточная память от непрерывного открытия и закрытия потоков.Есть идеи?

1 Ответ

0 голосов
/ 21 апреля 2011

Ваш подход верен: это рекомендуемый шаблон для сохранения основного потока для отзывчивости пользовательского интерфейса и запуска отдельного потока для ресурсоемких заданий, используя OpenMP (или любую другую параллельную среду) для параллельной обработки этого задания.

Почему он не использует все потоки / ядра HW таким способом - это отдельный вопрос. Это может быть связано с дисбалансом нагрузки, или некоторыми проблемами синхронизации, или значительными последовательными частями вычислений, или объемом работы, который все время недостаточен для всех потоков.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...