2013-08-06 70 views
1

通過2個線程程序在1個或2個內核上運行,確保實時性能得以實現的最佳方法是什麼? boost :: timer或RDTSC?表現測量:時間vs滴答?

我們從代碼

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; 
} 

開始,所以它在單線程/單核的方式運行,我們觀察到max_time_per_frame比因爲do_something_more處理的目標時較高。 爲了消除這些處理時間尖峯,我們在單獨的線程中開始每個do_something_more,就像下面的僞代碼一樣。

class Proc { 
public: 
    Proc() : _frame_counter(0) { 
     t = start_thread (do_something_more_thread); 
    } 

    // 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) 
     { 
      sem.up(); 
     } 
     _frame_counter++; 
    } 

    void do_something_more_thread() 
    { 
     while(1) 
     { 
      sem.down(); 
      do_something_more(); 
     } 
    } 

private: 
    _frame_counter; 
    semaphore sem; 
    thread t; 
} 

我總是在1和2核上啓動我的程序。所以我使用start /AFFINITY 1 pro.exestart /AFFINITY 3 prog.exe 從時間上看,每件事情都沒有問題,max_time_per_frame保持低於我們的目標,接近0.02秒/幀的平均水平。

但是,如果我轉儲在f中花費的tick的數量,使用RDTSC。

#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); 
} 

start /AFFINITY 3 prog.exe的max_tick_per_frame穩定,預期我看到了1個線程(1個核心的100%)和2號線開始以正常速度二號核心。

start /AFFINITY 1 pro.exe,我看到只有100%的核心(如預期),但do_something_more計算時間似乎並沒有在時間交錯的線程執行時間花費。事實上,我定期看到蜱蟲數量猛增。

所以問題是爲什麼?唯一有趣的措施是time?在1核心(頻率提升)上運行軟件時,tick是否有意義?

+1

我剛剛在這裏回答了一個類似的問題:http://stackoverflow.com/questions/18089219/obtaining-time-from-clock-cycles – zaufi

+2

我發表此評論以迴應提及.exe文件擴展名。如果您不使用Windows,我的道歉適用。簡而言之,您不能 - MS Windows不是實時操作系統(RTOS) - 您可以近距離使用Windows,但不會實時使用Windows。 – enhzflep

+0

@zaufi,看起來很相似,但我的結果相反,在1或2核上運行soft並不會真正改變'time',但是當在1核上運行/調度2線程時,'tick'的數量會增加對於1幀而不是幾個,就像在下一幀的實時處理期間附加線程執行時間未被擴展/交織一樣。 – alexbuisson

回答

1

雖然你永遠不會得到真正的實時性能,但你可以通過使用Windows API來減少RDTSC的缺陷。

這是一個利用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; 
} 

您還可以使用:

#include <Mmsystem.h> 
if(timeBeginPeriod(1) == TIMERR_NOCANDO) { 
    printf("TIMER could not be set to 1ms\n"); 
} 
/*-- your code here --*/ 
timeEndPeriod(1); 

但是,這將改變全球的窗口計時器分辨率到什麼都間隔將其設置爲(或者至少嘗試吧),所以我不會推薦這種方法,除非你100%確定你是唯一一個使用這個程序的人,因爲這可能會對其他程序產生意想不到的副作用。

+0

+1使用QueryPerformanceCounter並避免使用RDTSC。 –

0

根據有關REALTIME_PRIORITY_CLASS的註釋,我在測試程序中添加了以下行。

#define NOMINMAX 
#include <windows.h> 
.... 

SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS); 

現在滴答計數我從RDTSC得到更好看,龐大的秒殺我在1幀之前所看到的,現在分佈在多個幀。

boots::this_thread::yield(); 

,並與變化,我得到調度和RDTSC值I:

,因爲我想保持我的代碼移植,並創建一些調度機會,我使用產生額外的線程在某個特定點預計無需配置優先級!

感謝您的幫助和建議。