Шаблон проектирования для многопоточного общего отчета о проделанной работе - PullRequest
2 голосов
/ 12 октября 2011

У меня есть библиотека с сущностью IJobMaker, которая создает определенное количество IJob объектов для запуска в собственных потоках, управляемых пользователем.Чтобы отслеживать прогресс каждого IJob, я использую шаблон наблюдателя с IProgressObserver в каждой работе.Трудность возникает, когда я хочу сообщить о ВСЕМ прогрессе.

Для меня идеально было бы иметь IProgressOverserver.ReportProgress(float jobProgress, float overallProgress, который бы сообщал как о работе, так и об общем прогрессе. IJobMaker может знать часть каждой работы в общемработать и как-то собирать все отчеты.

Возникают два основных вопроса:

  1. Механизм синхронизации?Например, хранение мьютекса внутри IJobMaker может повредить производительности, поскольку IProgressOverserver.ReportProgress часто вызывается, а мьютекс может вызывать переключение контекста, а что нет.InterlockedIncrement выглядит хорошим вариантом, но, поскольку для плавающей запятой такой функции нет, я был бы вынужден сообщать о прогрессе с помощью целочисленных приращений.(Я хотел бы держаться подальше от функций c ++ 0x или Boost)

  2. Шаблон проектирования?Прогресс IJob сообщается из самых глубоких алгоритмов.Мне нужен каждый такой отчет для связи с центральной организацией для расчета общего прогресса и вызова метода IProgressObserver.ReportProgress, который находится в IJob.

Ответы [ 2 ]

1 голос
/ 12 октября 2011

Пара предложений по теме потоков:

  1. Не сообщайте о каждом крошечном прогрессе.Отправляйте отчеты в основной поток только после того, как будет достигнут определенный заранее определенный объем выполнения, или пройдет определенный заранее определенный промежуток времени, или подзадача завершена.Это может значительно сократить объем синхронизации.
  2. Если вы внедрите # 1, мьютекс может работать очень хорошо.
  3. Если мьютекс окажется слишком дорогим, вы можете сообщить о прогрессе.используя целочисленную атомарную переменную: просто масштабируйте значения от «нет прогресса» до «все сделано» до 0 ... INT_MAX.

Что касается проектирования API, то оно не должноСлишком сложно придумать что-нибудь разумное.Мой общий совет - не переусердствовать.

0 голосов
/ 13 октября 2011

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

Есть еще одно предложение. Вы можете использовать сегментацию - синхронизировать только несколько потоков одним мьютексом / атомарным (один сегмент). А затем собрать общее количество среди всех сегментов.

Кроме того, есть хорошее место, чтобы начать поиск высокопараллельных алгоритмов: http://www.1024cores.net/home/lock-free-algorithms

UDPATE Есть пример проблем с поплавком

#include <iostream>
using namespace std;
int main() {
    float f = 0;
    for(int i=0; i<100000-98; ++i)
    {
        f += 0.00001;
    }
    cout << f << endl;
}

Таким образом, если у вас 100 заданий с 1000 шагами в каждом, вы получите результат на 98 в 98 раньше, чем вы могли ожидать.

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