C++ 如何在不同的线程中保持一定的帧速率

C++ 如何在不同的线程中保持一定的帧速率,c++,multithreading,c++11,C++,Multithreading,C++11,我有两个不同的计算任务,必须以特定的频率执行。一个必须每1ms执行一次,另一个必须每13.3ms执行一次。这些任务共享一些数据 我很难安排这些任务以及如何在它们之间共享数据。我认为可行的一种方法是创建两个线程,每个任务一个线程 第一个任务相对简单,可以在1ms内完成。但是,当第二个任务(相对来说更耗时)即将启动时,它将复制任务1刚刚使用的数据,并继续处理这些数据 你觉得这样行吗?如何在C++中实现?< p>在C++中有多种方法。 一种简单的方法是使用2个线程,如您所述。每个线程执行其操作,然后休

我有两个不同的计算任务,必须以特定的频率执行。一个必须每1ms执行一次,另一个必须每13.3ms执行一次。这些任务共享一些数据

我很难安排这些任务以及如何在它们之间共享数据。我认为可行的一种方法是创建两个线程,每个任务一个线程

第一个任务相对简单,可以在1ms内完成。但是,当第二个任务(相对来说更耗时)即将启动时,它将复制任务1刚刚使用的数据,并继续处理这些数据


你觉得这样行吗?如何在C++中实现?

< p>在C++中有多种方法。

一种简单的方法是使用2个线程,如您所述。每个线程执行其操作,然后休眠到下一个周期开始:

#包括
#包括
#包括
#包括
#包括
#包括
std::互斥互斥;
std::原子停止={false};
未签名的最后结果=0;//任何线程_1ms产生的。
无效线程\u 1ms\u操作(){
//做这项工作。
//更新最后的结果。
{
std::唯一锁(互斥锁);
++最后的结果;
}
}
无效线程\u 1333us\u操作(){
//复制线程\u 1ms结果。
未签名的最后结果副本;
{
std::唯一锁(互斥锁);
last_result_copy=last_result;
}
//做这项工作。

STD::CUT< P>在C++中有多种方式来做。

一种简单的方法是,如您所述,有两个线程。每个线程执行其操作,然后休眠到下一个时段开始:

#包括
#包括
#包括
#包括
#包括
#包括
std::互斥互斥;
std::原子停止={false};
unsigned last_result=0;//线程\u 1ms产生的任何结果。
无效线程\u 1ms\u操作(){
//做这项工作。
//更新最后的结果。
{
std::唯一锁(互斥锁);
++最后的结果;
}
}
无效线程\u 1333us\u操作(){
//复制线程\u 1ms结果。
未签名的最后结果副本;
{
std::唯一锁(互斥锁);
last_result_copy=last_result;
}
//做这项工作。

std::cout所以我认为task1需要进行复制,因为它知道何时可以安全地进行复制

Shared:
    atomic<Result*> latestResult = {0};

Task1:
    Perform calculation
    Result* pNewResult = new ResultBuffer
    Copy result to pNewResult
    latestResult.swap(pNewResult)
    if (pNewResult)
        delete pNewResult; // Task2 didn't take it!

Task2:
    Result* pNewResult;
    latestResult.swap(pNewResult);
    process result
    delete pNewResult;
共享:
原子最新结果={0};
任务1:
计算
结果*pNewResult=newresultbuffer
将结果复制到pNewResult
最新结果交换(pNewResult)
if(pNewResult)
删除pNewResult;//Task2没有接受它!
任务2:
结果*pNewResult;
最新结果交换(pNewResult);
过程结果
删除pNewResult;
在这个模型中,task1和task2只在交换一个简单的原子指针时才会发出刺耳的声音,这是非常轻松的

请注意,这会对您的计算做出许多假设。例如,task1是否可以有效地将结果直接计算到缓冲区中?还请注意,在开始时,Task2可能会发现指针仍然为空

此外,它还低效地增加了缓冲区。您需要3个缓冲区来确保任务之间不会有任何明显的干扰,但您可以在互斥体下管理三个缓冲区指针,这样任务1将准备好一组数据,并正在写入另一组数据,而任务2正在读取第三组数据


请注意,即使让task 2复制缓冲区,task 1仍然需要2个缓冲区以避免暂停。

因此我认为task1需要进行复制,因为它知道何时可以安全地进行复制。下面是一个简单的模型:

Shared:
    atomic<Result*> latestResult = {0};

Task1:
    Perform calculation
    Result* pNewResult = new ResultBuffer
    Copy result to pNewResult
    latestResult.swap(pNewResult)
    if (pNewResult)
        delete pNewResult; // Task2 didn't take it!

Task2:
    Result* pNewResult;
    latestResult.swap(pNewResult);
    process result
    delete pNewResult;
共享:
原子最新结果={0};
任务1:
计算
结果*pNewResult=newresultbuffer
将结果复制到pNewResult
最新结果交换(pNewResult)
if(pNewResult)
删除pNewResult;//Task2没有接受它!
任务2:
结果*pNewResult;
最新结果交换(pNewResult);
过程结果
删除pNewResult;
在这个模型中,task1和task2只在交换一个简单的原子指针时才会发出刺耳的声音,这是非常轻松的

请注意,这会对您的计算做出许多假设。例如,task1是否可以有效地将结果直接计算到缓冲区中?还请注意,在开始时,Task2可能会发现指针仍然为空

此外,它还低效地增加了缓冲区。您需要3个缓冲区来确保任务之间不会有任何明显的干扰,但您可以在互斥体下管理三个缓冲区指针,这样任务1将准备好一组数据,并正在写入另一组数据,而任务2正在读取第三组数据


注意,即使任务2复制缓冲区,任务1仍然需要2个缓冲区来避免STORE。

< P>可以使用C++类线程和线程设施,如类<代码>线程< /C>和定时器类,如“代码> StestyLyCalths/Cuth>”,如前面的答案中所描述的,但是如果这个解决方案工作得很强,取决于您的代码i的平台。他继续跑

1ms和13.3ms是非常短的时间间隔,如果您的代码运行在非实时操作系统(如Windows或非RTOS Linux)上,则无法保证操作系统调度器会在准确的时间唤醒您的线程

C++ 11有C++类的代码,如果你的平台支持一个,但它仍然依赖于高分辨率定时器,但它仍然依赖于这个类的实现。而且,比计时器更大的问题是使用C++等待函数。你的线程在指定的时间。这里是C++文档的引用。< /P> sleep_for-在至少指定的sleep_持续时间内阻止当前线程的执行

幸运的是,大多数操作系统都有一些特殊的功能,比如Windows多媒体定时器,如果线程没有在预期时间唤醒,您可以使用它们


<>这里有更多的细节。

可以使用C++线程和线程设备,如类<代码>