2012-10-30 133 views
8

我有一臺帶有8個處理器的機器。我想用OpenMP和MPI對我這樣的代碼交替:OpenMP和MPI混合程序

OpenMP的階段:

  • 行列1-7等待一個MPI_Barrier
  • 等級0使用的所有8個處理器使用OpenMP

MPI階段:

  • 等級0達到屏障和各級使用一個處理器每個

到目前爲止,我已經做了:

  • 集I_MPI_WAIT_MODE 1,使居1-7不使用CPU,而在屏障。
  • 在等級0上設置omp_set_num_threads(8),以便它啓動8個OpenMP線程。

這一切工作。 0級確實發佈了8個線程,但都只限於一個處理器。在OpenMP階段,我從一個處理器上運行等級爲0的8個線程,並且所有其他處理器都處於空閒狀態。

如何讓MPI允許0級使用其他處理器?我正在使用英特爾MPI,但如果需要可以切換到OpenMPI或MPICH。

+1

我認爲這應該只是工作。你確定固定沒有啓用?檢查'I_MPI_PIN'設置。 –

+1

當然你已經啓用了進程鎖定。訣竅是,如果你禁用它,你的MPI過程將不再是核心約束,並且MPI部分的性能會下降。您可以通過編程方式更改CPU掩碼 - 保存它,允許OpenMP階段的所有處理器恢復掩碼。 –

回答

0

謝謝大家的意見和答案。你沒事。這都是關於「PIN」選項。

解決我的問題,我剛:

I_MPI_WAIT_MODE = 1

I_MPI_PIN_DOMAIN = OMP

這麼簡單。現在所有的處理器都可用於所有級別。

選項

I_MPI_DEBUG = 4個

顯示哪些處理器每個秩獲得。

+1

你所做的是有效地禁用進程鎖定 - 固定到所有可用CPU的進程根本不被鎖定。 –

13

以下代碼顯示瞭如何在OpenMP部件之前保存CPU親和性掩碼的示例,將其更改爲允許並行區域持續時間內的所有CPU,然後恢復以前的CPU關聯掩碼。該代碼是Linux專用的,如果您未啓用MPI庫的進程鎖定 - ,則通過在Open MPI中傳遞--bind-to-core--bind-to-socketmpiexec來激活是沒有意義的; 通過在Intel MPI中將I_MPI_PIN設置爲disable來取消激活(4.x上的默認設置爲引腳進程)。

#define _GNU_SOURCE 

#include <sched.h> 

... 

cpu_set_t *oldmask, *mask; 
size_t size; 
int nrcpus = 256; // 256 cores should be more than enough 
int i; 

// Save the old affinity mask 
oldmask = CPU_ALLOC(nrcpus); 
size = CPU_ALLOC_SIZE(nrcpus); 
CPU_ZERO_S(size, oldmask); 
if (sched_getaffinity(0, size, oldmask) == -1) { error } 

// Temporary allow running on all processors 
mask = CPU_ALLOC(nrcpus); 
for (i = 0; i < nrcpus; i++) 
    CPU_SET_S(i, size, mask); 
if (sched_setaffinity(0, size, mask) == -1) { error } 

#pragma omp parallel 
{ 
} 

CPU_FREE(mask); 

// Restore the saved affinity mask 
if (sched_setaffinity(0, size, oldmask) == -1) { error } 

CPU_FREE(oldmask); 

... 

您也可以調整的OpenMP的運行時的釘扎參數。對於GCC/libgomp,親和力由GOMP_CPU_AFFINITY環境變量控制,而對於英特爾編譯器,則爲KMP_AFFINITY。如果OpenMP運行時將所提供的親和性掩碼與進程的親緣性掩碼相交,則仍然可以使用上面的代碼。

只是爲了完整起見 - 節省,設置和恢復在Windows親和力掩碼:

#include <windows.h> 

... 

HANDLE hCurrentProc, hDupCurrentProc; 
DWORD_PTR dwpSysAffinityMask, dwpProcAffinityMask; 

// Obtain a usable handle of the current process 
hCurrentProc = GetCurrentProcess(); 
DuplicateHandle(hCurrentProc, hCurrentProc, hCurrentProc, 
       &hDupCurrentProc, 0, FALSE, DUPLICATE_SAME_ACCESS); 

// Get the old affinity mask 
GetProcessAffinityMask(hDupCurrentProc, 
         &dwpProcAffinityMask, &dwpSysAffinityMask); 

// Temporary allow running on all CPUs in the system affinity mask 
SetProcessAffinityMask(hDupCurrentProc, &dwpSysAffinityMask); 

#pragma omp parallel 
{ 
} 

// Restore the old affinity mask 
SetProcessAffinityMask(hDupCurrentProc, &dwpProcAffinityMask); 

CloseHandle(hDupCurrentProc); 

... 

應具有單個處理器的工作組(多達64個邏輯處理器)。