在Windows中的多线程中,时间消耗是不正常的

时间:2022-07-05 20:42:03

The time consume is not normal in multi-thread in Windows. Our device has 5 nozzles, the process is:

在Windows中的多线程中,时间消耗是不正常的。我们的设备有5个喷嘴,过程是:

  1. The nozzles pick chips up at the same time, so I use the 5 threads do it
  2. 喷嘴同时拾取芯片​​,所以我使用5个线程来做

  3. Move the nozzles to another place
  4. 将喷嘴移到另一个地方

  5. Put the chips
  6. 放芯片

It's smooth at normal time, but sometimes it has a short stop before moving to another place (we can see it obviously). Picking chips takes about 80 milliseconds at normal time, and sometimes it becomes 130 milliseconds. I write a simple code to test it:

它在正常时间是平滑的,但有时它在移动到另一个地方之前有一个短暂的停止(我们可以看到它)。拾取芯片在正常时间需要大约80毫秒,有时它变为130毫秒。我写了一个简单的代码来测试它:

#include "stdafx.h"
#include <WINDOWS.H>
#include <PROCESS.H>
#include <iostream>
#include <Mmsystem.h>

#pragma comment(lib, "winmm.lib")

using namespace std;

static TIMECAPS                 l_timecaps;

UINT WINAPI MainThread(LPVOID lParam /* = NULL */);
UINT WINAPI TestThread(LPVOID lParam /* = NULL */);
void MainProcess();

int _tmain(int argc, _TCHAR* argv[])
{
    //set current process priority as real time
    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);

    //use more accurate time
    timeGetDevCaps(&l_timecaps, sizeof(l_timecaps));
    timeBeginPeriod(l_timecaps.wPeriodMin);

    UINT uiThreadId = 0;
    HANDLE hEvents = (HANDLE) _beginthreadex(NULL, 0, MainThread, NULL, 0, &uiThreadId);
    SetThreadPriority(hEvents, THREAD_PRIORITY_TIME_CRITICAL);

    WaitForSingleObject(hEvents, INFINITE);

    cerr << endl << "Press Enter to exit." << endl;
    while (cin.get() != '\n');

    timeEndPeriod(l_timecaps.wPeriodMin);

    return 0;
}

UINT WINAPI MainThread(LPVOID lParam /* = NULL */)
{
    int i = 0;
    while (i < 100)
    {
        MainProcess();
        i++;
    }

    return 0;
}

void MainProcess()
{
    const int THREAD_NUMBER = 5;
    static HANDLE hEvents[THREAD_NUMBER]; 
    for (int i = 0; i < THREAD_NUMBER; ++i)
        hEvents[i] = NULL;

    //log time with more accurate time
    LARGE_INTEGER liPerfFreq={0};
    LARGE_INTEGER liBeginRunTime = {0}; 
    long lBeginRunTime = 0; 
    QueryPerformanceFrequency(&liPerfFreq); 
    QueryPerformanceCounter(&liBeginRunTime);
    lBeginRunTime = liBeginRunTime.QuadPart * 1000 / liPerfFreq.QuadPart;

    for (int i = 0; i < THREAD_NUMBER; ++i)
    {
        UINT uiThreadId = 0;
        hEvents[i] = (HANDLE) _beginthreadex(NULL, 0, TestThread, NULL, 0, &uiThreadId);
        SetThreadPriority(hEvents[i], THREAD_PRIORITY_TIME_CRITICAL);

        //assign to cpu
        SetThreadAffinityMask(hEvents[i], 0x00000001 + i);
    }

    //wait all threads finished
    WaitForMultipleObjects(THREAD_NUMBER, hEvents, TRUE, INFINITE);

    LARGE_INTEGER liEndRunTime = {0};
    long lEndRunTime = 0; 
    QueryPerformanceCounter(&liEndRunTime);
    lEndRunTime = liEndRunTime.QuadPart * 1000 / liPerfFreq.QuadPart;

    cout << "time: " << lEndRunTime - lBeginRunTime << endl;
}


UINT WINAPI TestThread(LPVOID lParam /* = NULL */)
{
    //do nothing
    return 0;
}

The output result time is 2,3 or 4 millisecond, but sometimes it becomes 57 or 62 millisecond. It's bad for our device when running, the device becomes slow.

输出结果时间为2,3或4毫秒,但有时会变为57或62毫秒。这对我们的设备运行不利,设备变慢。

1 个解决方案

#1


Your test threads do nothing. All the time is spent creating and shutting down the thread. Overheads in the kernel object manager and scheduler will dominate. Perhaps some of the threads are having to wait on other threads holding (via API calls) kernel locks and thus seeing delays.

你的测试线程什么都不做。所有的时间都花在创建和关闭线程上。内核对象管理器和调度程序中的开销将占主导地位。也许有些线程必须等待其他线程(通过API调用)内核锁定,从而看到延迟。

And of course those inner threads could be completing before the call to set their priority completes: to set this you really need to start the thread suspended and then start it.

当然,那些内部线程可能在调用之前完成设置其优先级完成:设置它你真的需要启动线程暂停然后启动它。

Because you are measuring nothing, all you have are overheads which will depend on what else is going on.

因为你什么都没做,所有你所拥有的都是管理费用,这取决于其他的情况。

Also remember, while you have names like THREAD_PRIORITY_TIME_CRITICAL Windows is not a real-time OS.

还要记住,虽然你有像THREAD_PRIORITY_TIME_CRITICAL这样的名字,但Windows不是实时操作系统。

#1


Your test threads do nothing. All the time is spent creating and shutting down the thread. Overheads in the kernel object manager and scheduler will dominate. Perhaps some of the threads are having to wait on other threads holding (via API calls) kernel locks and thus seeing delays.

你的测试线程什么都不做。所有的时间都花在创建和关闭线程上。内核对象管理器和调度程序中的开销将占主导地位。也许有些线程必须等待其他线程(通过API调用)内核锁定,从而看到延迟。

And of course those inner threads could be completing before the call to set their priority completes: to set this you really need to start the thread suspended and then start it.

当然,那些内部线程可能在调用之前完成设置其优先级完成:设置它你真的需要启动线程暂停然后启动它。

Because you are measuring nothing, all you have are overheads which will depend on what else is going on.

因为你什么都没做,所有你所拥有的都是管理费用,这取决于其他的情况。

Also remember, while you have names like THREAD_PRIORITY_TIME_CRITICAL Windows is not a real-time OS.

还要记住,虽然你有像THREAD_PRIORITY_TIME_CRITICAL这样的名字,但Windows不是实时操作系统。