2012-07-15 61 views
2

雖然使用OpenMP線程,OpenMP的線程,數據訪問延遲和STL數據容器

  1. 每個線程都可以宣佈自己的一套私有變量。假設 獲取每個線程專用的數據的延遲低於將數據可見 提取到所有線程的延遲時間是否正確?換句話說,線程局部變量緩存了

  2. 說每個線程,想要使用線程私有STL數據容器,如std::vector。在單線程C++ 代碼中,std::vector中的數據存儲在堆中。那麼多線程的情況呢? 線程專用std ::向量的數據是否仍然存儲在堆上?

回答

5

除非您使用的是NUMA機器,否則內存是統一的。

是否正確地假設,獲取每個線程專用的數據的延遲低於獲取所有線程可見的數據的延遲。

線程本地存儲本質上並不比所有線程都可見的內存「更快」。但是,僅由一個線程使用的內存不太可能受到緩存一致性影響 - 因爲它只能由單個線程訪問。

換句話說,線程局部變量是否被緩存?

不一定。如果它不適合CPU緩存,它肯定不會是這種情況。共享數據同時也可以位於多個內核的緩存中。

那麼多線程的情況呢? 線程專用std ::向量的數據是否仍然存儲在堆中?

是的,無論線程的數量如何,他們都會在堆中。

+0

重回你的第一句話,這是真的嗎?這與你的第二段有些矛盾,這也迴應了我的理解。 – 2012-07-15 16:11:12

+0

是的,我做了一個項目,我手動將數據分配到不同的NUMA節點,並將關聯的線程綁定到這些節點。 (因此是「微觀管理」部分) – Mysticial 2012-07-15 16:12:00

+0

我的意思是「內存或多或少是統一的」部分,而不是「除非」部分。 NUMA允許你有非統一的訪問權限是無可爭議的。 – 2012-07-15 16:13:33

3

在幾乎所有廣泛使用的OpenMP運行時中,私有變量和共享變量的實現都是不同的。

private自動變量駐留在每個正在執行的線程的堆棧中,並且threadprivate變量駐留在TLS中。自動私有變量也可以進行優化以照常註冊。

shared並行區域的變量通常實現爲一個結構,它通過地址作爲參數傳遞給每個線程函數,然後使用額外的指針取消引用來訪問每個共享變量。除了一些編譯器將共享變量視爲隱含地處理volatile併發布全部加載/更新/存儲指令的範圍,儘管OpenMP提供了一種寬鬆的內存模型,允許不同線程中共享變量的可見值之間存在某種程度的不一致性同步點,其中一個點是明確的flush指令(仍然flush是最廣泛誤解的OpenMP功能,甚至語言製造者也無法在標準文檔中獲得其使用權範例)。

至於在多線程情況下在堆中分配數據,堆操作本質上是序列化的,因爲大多數堆實現使用鏈接列表或類似的數據結構。除了通常的分配器不關心由不同線程分配的數據可能最終共享高速緩存行,並且這可能導致錯誤的共享和相關的性能損失。有專門的多線程分配器,如hoard,ptmalloc,umem,tcmalloc等,試圖解決這些問題的代價是更多的內存使用。其中一些(例如tcmalloc)也支持NUMA。 docs聲稱它做了某種「魔術」來讓STL容器使用它的分配器而不是默認的分配器,但我不能贊同,因爲我不是tcmalloc和C++的重量級用戶。

在NUMA系統上運行時需要考慮的一件事是線程綁定。一些OpenMP運行時已經包含了控制線程與內核綁定的規定,並且即將頒佈的OpenMP標準很可能包含用於指定綁定屬性的標準框架,正如語言委員會正在討論的那樣。