Совместное использование массива данных между потоками-C ++ - PullRequest
3 голосов
/ 01 октября 2010

Я знаю, что есть похожие вопросы, на которые уже дан ответ, но я задаю этот вопрос, поскольку они не дают точно то, что я хотел бы знать. Это о синхронизации между потоками. Идея моего проекта заключается в том, что мы получаем данные с карты сбора данных, строим и анализируем данные во время сбора данных. Пока у меня есть только класс для сбора данных в одном потоке и класс для построения в другом потоке. Класс сбора данных хранит данные в глобальном круговом буфере, а класс построения копирует данные из глобального буфера и выполняет некоторые процессы для построения графика (уменьшение точки данных и т. Д.). Это то, что я называю проблемой (одного) производителя (одного) потребителя. Мне удалось выполнить эту часть, используя два семафора, которые отслеживают, сколько точек данных хранится в классе сбора и сколько используется классом построения.

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

  1. Два считывателя используют один и тот же набор данных. Т.е. каждый произведенный предмет должен использоваться обоими читателями, вместо одного из них.
  2. Когда буфер заполняется, класс сбора данных перезаписывается глобальный буфер. Когда считыватель теряет данные из-за перезапись буфера класс сбора данных, это должно быть обнаружены и, в идеале, храниться в журнал (например, какая часть данные пропущены читателем (ями).
  3. Расчет анализа класс может быть интенсивным. За это, Мне может понадобиться больший буфер данных в класс анализа.

То, как я справился с первой частью (один производитель и один потребитель), похоже, не распространяется на случай второй части (один производитель и два потребителя). Мне интересно, как мне поступить. Я использую C ++ с Qt для многопоточности, так как я использую Qt для GUI. Но решение не обязательно должно быть с Qt. Тем не менее, если это возможно, примеры кодов или псевдокодов будут высоко оценены. Я нашел аналогичную тему для моей проблемы здесь ). Предлагается использовать boost :: interprocess. Однако, поскольку я никогда раньше не использовал библиотеку Boost и, хотя я читал документы о boost :: interprocess, она выглядит слишком сложной, чтобы понять это сам.

Большое спасибо!

Daisuke

Ответы [ 2 ]

2 голосов
/ 01 октября 2010

Если обоим потребителям нужно видеть все элементы данных, вам, вероятно, лучше иметь буфер для каждого потребителя. Затем производитель может разместить те же данные в каждом буфере. Если вас беспокоят требования к памяти для удвоения данных таким образом, и потребители не изменяют данные, вы можете использовать указатель с подсчетом ссылок, такой как boost::shared_ptr, и поместить указатель на данные в каждый буфер. Таким образом, элемент данных используется совместно, но читатели могут обрабатывать данные независимо друг от друга.

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

0 голосов
/ 01 октября 2010

Я думаю, вам следует прочитать следующие статьи по параллелизму, написанные Хербом Саттером, чтобы понять, как вы должны структурировать вещи и как их масштабировать (если это цель).Ссылка ниже является последней статьей, но также содержит полный список предыдущих.

http://herbsutter.com/2010/09/24/effective-concurrency-know-when-to-use-an-active-object-instead-of-a-mutex/

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

http://herbsutter.com/2008/05/23/effective-concurrency-maximize-locality-minimize-contention/

...