Вопрос связан с моим тестовым приложением, где у меня есть один мастер, координирующий большое количество подчиненных процессов. Все они совместно используют одну общую область памяти, где у каждого подчиненного процесса есть два семафора для синхронизации, один для обработки и один для ожидания завершения. Совместное использование данных невелико, но это тестовое приложение оказалось тяжелым при синхронизации.
Общая память создается
fd = shm_open(name, O_CREAT ...);
ftruncate(fd, SIZE_OF_SHARED_MEMORY);
void *p = mmap(NULL, SIZE_OF_SHARED_MEMORY, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
Теперь представьте, что структура имеет следующую структуру
struct shared_data {
sem_t run[NUMBER_OF_CHILDS];
sem_t ready[NUMBER_OF_CHILDS];
char data[N];
}
Основной процесс должен вызывать sem_post()
на некоторых семафорах run
, но не на всех, и ждать на sem_wait()
семафорах ready
с равным индексом. Ведомые процессы делают наоборот: они ждут один run
семафор, обрабатывают данные и публикуют ready
семафор.
Теперь это не очень медленно, на самом деле довольно быстро. Но представьте, что есть 1000 рабов, и я хочу разбудить 100 из них. Я бы предположил, что sem_post()
действительно вызывает некоторую низкоуровневую синхронизацию на уровне ЦП, которая является медленной. Таким образом, все процессоры и память остаются синхронизированными c. Но если я знаю, что собираюсь открыть набор семафоров, и можно открыть их все одновременно.
Вопрос в том, можно ли как-то увеличить все семафоры одним go ? Возможно ли это, аппаратно, я имею в виду? То, что мне нужно, это то, что разбивает sem_post()
на две операции, сначала изменяет память всех семафоров, а затем синхронизирует память. В тех случаях, когда реализация имеет значение, Linux на x86_64 является единственной целью здесь.
Или, можете ли вы предложить какое-либо другое решение этой проблемы? Производительность является единственным фактором здесь.