0

我目前正在试验多线程同步。对于背景,我有一组大约 100000 个对象 - 可能更多 - 我想以不同的方式每秒处理多次。

现在最关心我的是同步的性能。

这是我认为应该可以正常工作的(我省略了所有安全方面,因为这只是一个测试程序,如果出现错误,程序只会崩溃..)。我写了两个函数,第一个由程序的主线程执行,第二个由所有附加线程运行。

void SharedWorker::Start()
{
    while (bRunning)
    {
        // Send the command to start task1
        SetEvent(hTask1Event);

        // Do task1 (on a subset of all objects) here

        // Wait for all workers to finish task1
        WaitForMultipleObjects(<NumberOfWorkers>, <ListOfTask1WorkerEvents>, TRUE, INFINITE);

        // Reset the command for task1
        ResetEvent(hTask1Event);

        // Send the command to start task2
        SetEvent(hTask2Event);

        // Do task2 (on a subset of all objects) here

        // Wait for all workers to finish task2
        WaitForMultipleObjects(<NumberOfWorkers>, <ListOfTask2WorkerEvents>, TRUE, INFINITE);

        // Reset the command for task2
        ResetEvent(hTask2Event);

        // Send the command to do cleanup
        SetEvent(hCleanupEvent);

        // Do some (on a subset of all objects) cleanup

        // Wait for all workers to finish cleanup
        WaitForMultipleObjects(<NumberOfWorkers>, <ListOfCleanupWorkerEvents>, TRUE, INFINITE);

        // Reset the command for cleanup
        ResetEvent(hCleanupEvent);
    }
}

DWORD WINAPI WorkerThreads(LPVOID lpParameter)
{
    while (bRunning)
    {
        WaitForSingleObject(hTask1Event, INFINITE);

        // Unset finished cleanup
        ResetEvent(hCleanedUp);

        // Do task1 (on a subset of all objects) here

        // Signal finished task1
        SetEvent(hTask1);

        WaitForSingleObject(hTask2Event, INFINITE);

        // Reset task1 event
        ResetEvent(hTask1);

        // Do task2 (on a subset of all objects) here

        // Signal finished task2
        SetEvent(hTask2);

        WaitForSingleObject(hCleanupEvent, INFINITE);

        // Reset update event
        ResetEvent(hTask2);

        // Do cleanup (on a subset of all objects) here

        // Signal finished cleanup
        SetEvent(hCleanedUp);
    }

    return 0;
}

为了指出我的要求,我只给你一个小例子:假设我们从上面得到 100000 个对象,分成 8 个子集,每个子​​集 12500 个对象,一个具有 8 个逻辑内核的现代多核处理器。相关部分是时间。所有任务必须在大约 8ms 内完成。

我现在的问题是,我能否从拆分处理中获得显着的时间提升,或者通过事件进行同步是否过于昂贵?或者如果所有任务都需要以这种方式完成,是否还有另一种方式可以以更少的努力或处理时间来同步线程?

4

1 回答 1

0

如果您对单个对象的处理速度很快,请不要在线程之间拆分它。Windows 上的线程同步在每次上下文切换时都会消耗超过 50 毫秒。这个时间不被系统使用,而只是系统上运行其他东西的时间。

但是,如果每个对象处理将花费大约 8 毫秒,则需要跨线程池调度工作。但是,对象处理可能会有所不同,并且大量工作线程将在不同的时刻完成工作。

更好的方法是组织一个同步的对象队列,您可以将对象添加到其中进行处理,并从中取出它们进行处理。此外,由于单个对象的处理远低于线程的调度间隔,因此最好将它们分批进入处理线程(如10-20)。您可以估计池中的最佳工作线程数以及带有测试的批次的最佳大小。

所以伪代码看起来像:

main_thread:
    init queue
    start workers

    set counter to 100000
    add 100000 objects to queue
    while (counter) wait();

worker_thread:
    while (!done)
        get up to 10 objects from queue
        process objects
        counter -= processed count
        if (counter == 0) notify done
于 2013-03-19T14:02:11.817 回答