LINUX.ORG.RU

Я познаю мир. Многопоточность.

 , ,


0

1

Доброго всем времени суток. Сразу извиняюсь за сумбурную постановку вопроса. Помогите, пожалуйста, советом. Есть код, который работает с изображениями (пытаюсь разобраться с трекингом объектов на видео). В методе одного из классов изображение разбивается на области и передается методу другого класса для анализа на соответствие по некоторым параметрам. Точнее будет сказать: передается изображение целиком по ссылке (в интегральном виде) и вторым параметром идут координаты интересующей нас прямоугольной области. Сейчас это все работает, но очень медленно, так как каждая область обрабатывается последовательно. Вот и возникло желание это все распараллелить. Но тут возник вопрос: как избавиться от гонки состояний из-за того, что второй класс, который анализирует нужную область, в ходе анализа меняет свое состояние (в нем есть массивы, элементы которых меняют значение в зависимости от результата анализа конкретной области, причем индекс изменяемого элемента в массиве может совпадать для разных областей изображения, которые, в свою очередь, могут одновременно анализироваться в разных потоках). С многопоточностью в таком виде раньше дел не имел вообще. На подсознании понимаю, что где-то, что-то нужно блокировать но не до конца. Может есть хорошие статьи по этому поводу, чтобы не городить ненужные велосипеды, а то кругом одно и тоже пишут, но совсем не то, что меня интересует (может неправильно формулирюу вопрос?).

Если все блокировать, то никакой многопоточки не получится. Я бы тогда сделал области непересекающимися и для каждой области свой локальный набор данных. Тогда никаких (почти) блокировок и не потребуется.

Gorthauer ★★★★★ ()

Попробуй для начала обернуть те массивы в mutex/spinlock/rwlock в зависимости от способа доступа. Блокировать надо то, что вместе читается-пишется, очевидно.

anonymous ()

Видимо все-таки не получится сделать то, чего хочется. Проблема в том, что локально сделать это все не выйдет (на данном этапе). А если блокировать, то все потоки будут ждать один, пока он не закончит свою работу, так как блокировать придется весь массив. В общем смысла нет. Буду думать как это все переделать. Всем спасибо.

baldman88 ()

Что значит класс меняет состояние? У тебя там что статические поля используются или глобальные переменные?

FreeLiver ★★★ ()
Ответ на: комментарий от four_str_sam

В том-то и дело, что пока я не знаю как это сделать. Каждый проход (обработка одной области), по задумке, меняет состояние элементов массива в зависимости от его начального состояния. Просто изначально, из-за отсутствия опыта, о многопоточности не подумал, со всеми вытекающими отсюда последствиями.

baldman88 ()
Ответ на: комментарий от four_str_sam

Добиться того что бы обработчики изображений не влияли своей работой друг на друга.

Плюсую, перед тем как что-то блокировать, нужно сначала разнести задачи так, чтоб они работали либо каждая со своими данными, либо с общими, но неизменяемыми данными. И в одном из отдельных потоков уже ждать окончание/складывать результаты.

anonymous ()
Ответ на: комментарий от baldman88

Каждый проход (обработка одной области), по задумке, меняет состояние элементов массива в зависимости от его начального состояния

А скопировать именно эту область перед обработкой слишком затратно?

anonymous ()
Ответ на: комментарий от FreeLiver

Что-то вроде того. В классе есть массив. Вот его значения и меняются после каждого вызова одного из его методов. Причем меняются в зависимости от значения его элементов до вызова этого метода. Порочный круг в общем.

baldman88 ()
Ответ на: комментарий от baldman88

Что-то вроде того. В классе есть массив. Вот его значения и меняются после каждого вызова одного из его методов. Причем меняются в зависимости от значения его элементов до вызова этого метода. Порочный круг в общем.

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

FreeLiver ★★★ ()
Ответ на: комментарий от baldman88

К примеру, у меня есть три массива(positives, negatives, posteriors) размером array_size. Вот кусочек псевдокода с примерной логикой:

void classify(frame, ROI)
{
    int value = some_function(frame, ROI);
    for (int i = 0; i < array_size; i++) {
        if (value >= some_vale) {
            positives[i]++;
        } else {
            negatives[i]++;
        }
        if (positives[i] > 0) {
            posteriors[i] = positives[i] / (positives[i] + negatives[i]);
        }
    }
}

baldman88 ()
Ответ на: комментарий от baldman88

Вот этот кусок, я так понимаю, и нужно блокировать. Но тогда другие потоки будут ждать один и весь смысл распараллеливаня пропадает.

baldman88 ()
Ответ на: комментарий от baldman88

Не видно тут зависимостей, возможно тебе просто атомарные инкременты нужны? Если атомарность нужна на все три массива одновременно, и они фигурируют в some_function(), то действительно нечего распараллелить.

anonymous ()

Если там циклы во все поля, возможно, некоторый профит можно получить малой кровью с использованием openmp.

unC0Rr ★★★★★ ()
Ответ на: комментарий от baldman88

напиши перед циклом

#pragma omp parallel for shared(positives, negatives, posteriors) private(i)
/thread

anonymous ()
Ответ на: комментарий от unC0Rr

openmp

Фу, какая дрянь, лучше брать GCD

anonymous ()
Ответ на: комментарий от anonymous

Специально не замерял, но в 3 раза точно (до этого обрабатывало примерно 6 кадров в секунду, теперь 18, но тут уже ограничение используемой камеры — это максимум, который она может выдать).

baldman88 ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.