C++ 绩效衡量:时间与刻度?
在1个或2个内核上运行2线程程序时,确保实现实时性能的最佳方法是什么?boost::定时器还是RDTSC? 我们从那个代码开始C++ 绩效衡量:时间与刻度?,c++,multithreading,performance,C++,Multithreading,Performance,在1个或2个内核上运行2线程程序时,确保实现实时性能的最佳方法是什么?boost::定时器还是RDTSC? 我们从那个代码开始 boost::timer t; p.f(frame); max_time_per_frame = std!::max(max_time_per_frame, t.ellapsed()); ... where p is an instance of Proc. class Proc { public: Proc() : _frame_counter(0) {}
boost::timer t;
p.f(frame);
max_time_per_frame = std!::max(max_time_per_frame, t.ellapsed());
... where p is an instance of Proc.
class Proc {
public:
Proc() : _frame_counter(0) {}
// that function must be call for each video frame and take less than 1/fps seconds
// 24 fps => 1/24 => < 0.04 seconds.
void f(unsigned char * const frame)
{
processFrame(frame); //that's the most important part
//that part run every 240 frame and should not affect
// the processFrame flow !
if(_frame_counter % 240 == 0)
{
do_something_more();
}
_frame_counter++;
}
private:
_frame_counter;
}
我总是在1核和2核上开始我的程序。因此我使用start/AFFINITY 1pro.exe
或start/AFFINITY 3prog.exe
从时间的角度来看,一切正常,max\u time\u per\u frame
低于我们的目标,接近0.02秒/帧的平均值
但是如果我使用RDTSC转储在f中花费的滴答数
#include <intrin.h>
...
unsigned long long getTick()
{
return __rdtsc();
}
void f(unsigned char * const frame)
{
s = getTick();
processFrame(frame); //that's the most important part
//that part run every 240 frame and should not affect
// the processFrame flow !
if(_frame_counter % 240 == 0)
{
sem.up();
}
_frame_counter++;
e = getTick();
dump(e - s);
}
#包括
...
无符号long-long-getTick()
{
返回uu rdtsc();
}
void f(无符号字符*常量帧)
{
s=getTick();
processFrame(frame);//这是最重要的部分
//该部分每240帧运行一次,不应影响
//流程框架流!
如果(_帧_计数器%240==0)
{
sem.up();
}
_帧计数器++;
e=getTick();
垃圾场(e-s);
}
start/AFFINITY 3 prog.exe
max_tick_per_frame是稳定的,正如预期的那样,我看到1个线程(1个核心的100%),第2个线程以正常速度在第2个核心上启动
start/AFFINITY 1 pro.exe
,我只看到了一个100%的内核(正如预期的那样),但是do\u something\u more
计算时间似乎并没有随着时间的推移而延长,交错线程执行。事实上,每隔一段时间,我就看到了蜱虫数量的大幅增加
那么问题是为什么?唯一有趣的度量是时间吗?
勾选
在单核上运行软件(频率提升)时是否有意义?尽管在windows之外永远无法获得真正的实时性能,但您可以通过使用
下面是一个利用API的小代码块
#include <Windows.h>
#include <stdio.h>
int
main(int argc, char* argv[])
{
double timeTaken;
LARGE_INTEGER frequency;
LARGE_INTEGER firstCount;
LARGE_INTEGER endCount;
/*-- give us the higheest priority avaliable --*/
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
/*-- get the frequency of the timer we are using --*/
QueryPerformanceFrequency(&frequency);
/*-- get the timers current tick --*/
QueryPerformanceCounter(&firstCount);
/*-- some pause --*/
Sleep(1);
/*-- get the timers current tick --*/
QueryPerformanceCounter(&endCount);
/*-- calculate time passed --*/
timeTaken = (double)(doubleendCount.QuadPart-firstCount.QuadPart)/(double)(frequency.QuadPart/1000);
printf("Time: %lf", timeTaken);
return 0;
}
#包括
#包括
int
main(int argc,char*argv[])
{
双倍时间;
大整数频率;
大整数firstCount;
大整数结束计数;
/*--给我们最高的优先权--*/
SetThreadPriority(GetCurrentThread(),线程优先级时间临界);
/*--获取我们正在使用的计时器的频率--*/
QueryPerformanceFrequency(&frequency);
/*--获取计时器当前的滴答声--*/
QueryPerformanceCounter(&firstCount);
/*--停顿一下--*/
睡眠(1);
/*--获取计时器当前的滴答声--*/
QueryPerformanceCounter(&endCount);
/*--计算经过的时间--*/
所用时间=(double)(doubleendCount.QuadPart firstCount.QuadPart)/(double)(frequency.QuadPart/1000);
printf(“时间:%lf”,耗时);
返回0;
}
您还可以使用:
#include <Mmsystem.h>
if(timeBeginPeriod(1) == TIMERR_NOCANDO) {
printf("TIMER could not be set to 1ms\n");
}
/*-- your code here --*/
timeEndPeriod(1);
#包括
if(timeBeginPeriod(1)=TIMERR\u NOCANDO){
printf(“计时器无法设置为1ms\n”);
}
/*--你的代码在这里--*/
timeEndPeriod(1);
但这会将全局windows计时器分辨率更改为您将其设置为(或至少尝试设置)的时间间隔,因此,除非您100%确定自己是唯一使用此程序的人,否则我不会推荐这种方法,因为这可能会对其他程序产生意外的副作用。尽管在windows之外您永远无法获得真正的实时性能,但您可以通过使用 下面是一个利用API的小代码块
#include <Windows.h>
#include <stdio.h>
int
main(int argc, char* argv[])
{
double timeTaken;
LARGE_INTEGER frequency;
LARGE_INTEGER firstCount;
LARGE_INTEGER endCount;
/*-- give us the higheest priority avaliable --*/
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
/*-- get the frequency of the timer we are using --*/
QueryPerformanceFrequency(&frequency);
/*-- get the timers current tick --*/
QueryPerformanceCounter(&firstCount);
/*-- some pause --*/
Sleep(1);
/*-- get the timers current tick --*/
QueryPerformanceCounter(&endCount);
/*-- calculate time passed --*/
timeTaken = (double)(doubleendCount.QuadPart-firstCount.QuadPart)/(double)(frequency.QuadPart/1000);
printf("Time: %lf", timeTaken);
return 0;
}
#包括
#包括
int
main(int argc,char*argv[])
{
双倍时间;
大整数频率;
大整数firstCount;
大整数结束计数;
/*--给我们最高的优先权--*/
SetThreadPriority(GetCurrentThread(),线程优先级时间临界);
/*--获取我们正在使用的计时器的频率--*/
QueryPerformanceFrequency(&frequency);
/*--获取计时器当前的滴答声--*/
QueryPerformanceCounter(&firstCount);
/*--停顿一下--*/
睡眠(1);
/*--获取计时器当前的滴答声--*/
QueryPerformanceCounter(&endCount);
/*--计算经过的时间--*/
所用时间=(double)(doubleendCount.QuadPart firstCount.QuadPart)/(double)(frequency.QuadPart/1000);
printf(“时间:%lf”,耗时);
返回0;
}
您还可以使用:
#include <Mmsystem.h>
if(timeBeginPeriod(1) == TIMERR_NOCANDO) {
printf("TIMER could not be set to 1ms\n");
}
/*-- your code here --*/
timeEndPeriod(1);
#包括
if(timeBeginPeriod(1)=TIMERR\u NOCANDO){
printf(“计时器无法设置为1ms\n”);
}
/*--你的代码在这里--*/
timeEndPeriod(1);
但这会将全局windows计时器分辨率更改为您将其设置为(或至少尝试设置)的时间间隔,因此,除非您100%确定您是唯一使用此程序的人,否则我不会推荐这种方法,因为这可能会对其他程序产生意外的副作用。基于对REALTIME\u PRIORITY\u类的评论,我在测试程序中添加了以下行
#define NOMINMAX
#include <windows.h>
....
SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
通过这一更改,我获得了我期望的调度和RDTSC值,而无需配置优先级
感谢所有的帮助和建议。基于对REALTIME_PRIORITY_类的评论,我在测试程序中添加了以下行
#define NOMINMAX
#include <windows.h>
....
SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
通过这一更改,我获得了我期望的调度和RDTSC值,而无需配置优先级
感谢所有的帮助和建议。我刚刚回答了一个类似的问题:我是在看到有人提到.exe文件扩展名时发表这一评论的。如果您不使用Windows,我深表歉意。简单地说,你不能-MS Windows不是实时操作系统(RTOS)-你可以接近,但Windows永远不会实时。@zaufi,看起来很相似,但我的结果是相反的,在1核或2核上运行软件并不会真正改变
时间
,但是在1核上运行/调度2线程时,tick
的数量在一帧内增加,而不是在几帧内增加,比如在下一帧的实时处理过程中,额外的线程执行时间没有分散/交错。您是否意识到即使在实时操作系统上,RDTSC也存在许多问题?我不认为这是一个很好的选择时间任何东西,即使在非常规范