2016-12-04 57 views
0

我試圖在我的應用程序中測試一些功能,以查看它們需要多長時間。我使用鏈接列表在內存中記錄所有時間。在OMP區域鎖定

在這個過程中,我介紹了一個跟蹤列表的末尾的一個全局變量。當我進入一個新的時間區域時,我在列表的最後插入一條新記錄。相當簡單的東西。

但是,我想跟蹤的一些函數在OpenMP區域中調用。這意味着他們可能會被並行調用多次。這就是我難住的地方。

如果這是正常使用的Pthreads,我想簡單地包裹訪問全局變量的互斥和收工。但是,我不確定:這個策略是否仍然可以在OpenMP區域中調用函數?如在,他們會尊重鎖?

例如(不會編譯,但我覺得跨獲取點):

Record *head; 
Record *tail; 

void start_timing(char *name) { 
    Record *r = create_record(name); 
    tail->next_record = r; 
    tail = r; 
    return r; 
} 

int foo(void) { 
    Record r = start_timing("foo"); 
    //Do something... 
    stop_timing(r); 
} 

int main(void) { 
    Record r = start_timing("main"); 
    //Do something... 
    #pragma omp parallel for... 
    for (int i = 0; i < 42; i++) { 
     foo(); 
    } 
    //Do some more... 
    stop_timing(r); 
} 

哪個我會再更新到:

void start_timing(char *name) { 
    Record *r = create_record(name); 

    acquire_mutex_on_tail(); 
    tail->next_record = r; 
    tail = r; 
    release_mutex_on_tail(); 

    return r; 
} 

(道歉,如果這有一個明顯的答案 - 我對OpenMP框架和一般多線程相對缺乏經驗)。

+0

如果您的Openmp基於pthreads(通常是Linux或osx上的情況),它應該可以工作。 – tim18

回答

2

慣用的互斥解決方案是使用OpenMP鎖:

omp_set_lock(&taillock) 
tail->next_record = r; 
tail = r; 
omp_unset_lock(&taillock) 

和某處:

omp_lock_t taillock; 
omp_init_lock(&taillock); 

... 

omp_destroy_lock(&taillock); 

簡單的OpenMP溶液:

void start_timing(char *name) { 
    Record *r = create_record(name); 
    #pragma omp critical 
    { 
     tail->next_record = r; 
     tail = r; 
    } 
    return r; 
} 

這就產生一個隱式的全局鎖定結合到源代碼行。有關詳細的討論,請參閱this question的答案。

出於實用目的,使用Pthread的鎖也將工作,至少對其中的OpenMP是基於Pthreads的情景。

一個警告字

在性能測量代碼中使用鎖定是危險的。內存分配也是如此,這通常也意味着使用鎖。這意味着,start_time具有顯着的成本,並且性能會隨着更多的線程而變得更糟。這甚至不考慮讓一個線程分配一塊內存(記錄)然後另一個線程修改它(尾指針)的緩存失效。

現在可能是罰款,如果你測量的部分需要幾秒鐘,但它會造成很大的開銷,擾動當你的部分只有幾百個週期。

要創建一個可擴展的性能跟蹤工具,則必須預先分配較大的塊線程本地內存,只有到它的本地部分每個線程寫入。

您也可以選擇使用一些現有的測量基礎設施,如Score-P

架空&擾動

第一,二(聯概念)之間進行區分。 開銷是您花費的額外時間,而擾動指的是對您測量的結果(即您現在測量的結果與未進行測量的結果不同)。開銷是大量不希望的,但擾動要糟糕得多。

是的,您可以通過在昂貴的測量運行時期間暫停定時器來避免一些干擾(開銷仍然存在)。但是,在多線程環境中,這仍然是非常有問題的。

  • 減慢一個線程的進度,可能導致其他線程等待它,例如,在一個隱含的障礙期間。你如何將這個線程的等待時間和其他傳遞的等待時間歸因於什麼?
  • 內存分配通常被鎖定 - 所以如果您在測量運行時期間分配內存,則會減慢依賴於內存分配的其他線程。你可以嘗試減輕內存池,但是我會避免鏈接列表。
+0

感謝Score-P鏈接;我必須更徹底地調查它!問題:我應該提到,在進入內部函數之前,我正在「暫停」外部函數的時間,以及從內部函數返回的恢復時間。因此,鎖定和malloc不應該被捕獲在我的計時信息中。如果我直到鎖定和內存分配之後纔開始計時(例如,我將malloc記錄,鎖定並插入到位,然後開始計時),那麼我是否仍會遇到該性能開銷問題? – tonysdg

+0

請看我添加的最後一段。 – Zulan

+0

Amazimg答案。非常感謝! – tonysdg