Синхронизация циклических потоков - PullRequest
0 голосов
/ 22 января 2012

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

        // at end of loop on each thread...
        sig_thread_done();

        while (!is_sync_done())
        {
            PauseExecution(1);
        }

sig_thread_done и is_sync_done являются объектами функций из другого класса, который управляет списком всех «потоков».Эти функции выглядят так:

bool Core::IsFrameDone()
{
    MutexLock lock(manager_mutex);

    if (waiting_components == -1)
    {
        waiting_components = 0;
        return true;
    }
    return false;
}

void Core::SignalFrameDone()
{
    MutexLock lock(manager_mutex);

    if (++waiting_components == (int)components.size()) // components == threads
    {
        //sync shared data...
        waiting_components = -1; // -1 signifies that all threads have completed their iteration
    }
}

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

Я не могу найти простой способ решить эту проблему.Мне очень нравится этот подход, потому что синхронизация не останавливается, пока какой-то независимый поток выполняет синхронизацию.

Я ценю любые идеи или предложения, которые кто-либо может предложить.

Ссылка на статью.

Ответы [ 2 ]

0 голосов
/ 22 января 2012

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

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

0 голосов
/ 22 января 2012

Я думаю, вы пытаетесь заново изобрести Нитевой барьер .

...