簡體   English   中英

C ++ NUMA優化

[英]C++ NUMA Optimization

我正在研究最初為多核處理器系統開發的舊應用程序。 為了利用多核處理,已使用OpenMP和PPL。 現在,新要求是在具有多個NUMA節點的系統上運行該軟件。 目標操作系統是Windows 7 x64。

我進行了幾次測量,發現將應用程序分配給單個NUMA節點並浪費整個處理器時,執行時間是最佳的。 應用程序的許多部分執行數據並行算法,例如,並行處理向量的每個元素,然后將結果寫入另一個向量,如以下示例所示

std::vector<int> data;
std::vector<int> res;

// init data and res

#pragma omp parallel for
for (int i = 0; i < (int) data.size(); ++i)
{  
  res[i] = doExtremeComplexStuff(data[i]);
}

據我所知,此類算法的性能下降是由於來自第二個NUMA節點的非本地內存訪問引起的。 所以問題是如何使應用程序性能更好。

是否以某種方式透明地加速了對非本地內存的只讀訪問(例如,通過OS將數據從一個節點的本地內存復制到另一節點的本地內存)? 我是否需要拆分問題大小,然后將輸入數據復制到相應的NUMA節點,進行處理,然后再次合並所有NUMA節點的數據以提高性能?

如果是這種情況,是否有替代std容器的方法,因為這些方法在分配內存時不支持NUMA?

當您分配動態內存時(例如std::vector這樣做),您可以有效地從虛擬內存空間中獲取一定范圍的頁面。 當程序首次訪問特定頁面時,將觸發頁面錯誤,並請求物理內存中的某些頁面。 通常,該頁面位於生成頁面錯誤的核心的本地物理內存中,這稱為“ 首次觸摸策略”。

在您的代碼中,如果std::vector緩沖區的頁面首先被單個(例如,主)線程觸摸,則可能會發生這些矢量的所有元素最終存儲在單個NUMA節點的本地內存中的情況。 然后,如果將程序拆分為在所有NUMA節點上運行的線程,則使用這些向量時,某些線程將訪問遠程內存。

因此,解決方案是分配“原始內存”,然后首先以所有線程“觸摸”它的方式相同,然后在處理階段將這些線程訪問它們。 不幸的是,使用std::vector ,至少使用標准分配器,很難做到這一點。 您可以切換到普通動態數組嗎? 我將首先嘗試一下,以了解它們關於首次觸摸策略的初始化是否有幫助:

int* data = new int[N];
int* res = new int[N];

// initialization with respect to first touch policy
#pragma omp parallel for schedule(static)
for (int i = 0; i < N; i++) {
   data[i] = ...;
   res[i] = ...;
}

#pragma omp parallel for schedule(static)
for (int i = 0; i < N; i++)
   res[i] = doExtremeComplexStuff(data[i]);

使用static調度,在兩個循環中元素到線程的映射應該完全相同。


但是,我不相信您的問題是由訪問這兩個向量時的NUMA效應引起的。 當您調用函數doExtremeComplexStuff ,該函數似乎對於運行時非常昂貴。 如果真是這樣,那么與函數調用相比,即使訪問遠程NUMA內存也可能微不足道。 整個問題可以隱藏在此函數中,但我們不知道它是做什么的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM