Реализация локальных переменных задачи для параллелизма

Я улучшаю приложение (Win64, C ++), делая его более асинхронным. Я использую Concurrency Runtime, и он отлично работает для меня.

Приложение в основном выполняет ряд «заданий», преобразующих данные. Для отслеживания того, что делает каждое задание, некоторые подсистемы снабжены кодом для отслеживания определенных операций, которые выполняет задание. Ранее при этом использовалась бы одна глобальная переменная, представляющая выполняемое в данный момент задание, чтобы иметь возможность регистрировать информацию отслеживания без необходимости передавать контекстную информацию по всей цепочке вызовов. Каждое задание также может использовать ConcRT для распараллеливания самого задания. Это все работает довольно хорошо.

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

Что мне в основном нужно, так это способ связать некоторую контекстную информацию с Задачей и передать ее в любые другие задачи, порожденные этой задачей. По сути, мне нужны переменные «Task Local».

С ConcRT мы не можем просто использовать локальные потоки для хранения контекстной информации, так как задание может порождать другие задания с использованием ConcRT, и они будут выполняться в любом количестве потоков.

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

Итак, есть ли лучший способ сделать это? Мне бы очень хотелось иметь первоклассный механизм TaskLocal / userdata, который позволял бы мне связать единственный указатель контекста с текущим Scheduler / SchedulerGroup / Task, который я мог бы получить с очень небольшими накладными расходами.

Мой идеал — ловушка, которая вызывается всякий раз, когда поток ConcRT захватывает новую задачу, так как я мог бы затем получить идентификатор Scheduler / ScheduleGroup и сохранить его в локальном потоке для минимальных издержек доступа. Увы, я не вижу никакого способа зарегистрировать такой хук, и кажется невозможным реализовать пользовательские классы планировщика для PPL / агентов (см. Эта статья).

6

Решение

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

Если внедрение зависимости не вариант, есть другая стратегия для работы с синглетонами. Эта стратегия в основном позволяет Синглтону быть «стеком». Вы можете «вставить» новое значение в Singleton, и тогда каждый, кто получит к нему доступ, получит это новое значение. И тогда вы можете «вытолкнуть» значение обратно, и значение до нажатия будет восстановлено. Это не должно быть напрямую смоделировано с реальным стеком, поэтому я поместил слова «push», «pop» и «stack» в кавычки.

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

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]