2013-07-01 29 views
3

我有一個真正的困惑你的人。在RHEL5上隨機崩潰,使用短c openmp程序

下面是一個小型的自包含的簡單的40行程序,用於計算我正在使用的分佈式內存羣集上的一些數字的部分和,並定期(但隨機)崩潰節點。如果我產生了50個運行此代碼的PBS作業,則其中的0到4個會使其節點崩潰。它會在每次主循環的不同重複時發生,並且每次都在不同的節點上發生,但沒有可辨別的模式。節點只是在神經節報告上「下」,我不能ssh給他們(「沒有路由到主機」)。如果不是提交作業,而是將作業提交到其中一個節點並在那裏運行我的程序,如果我運氣不好並且崩潰,那麼我會停止查看文本,然後看到該節點已死在神經節上。

該程序是用openmp進行線程化處理,並且只有當大量線程被產生時纔會發生崩潰(如12)。

它的殺羣集是RHEL 5簇與具有2 6核X5650處理器節點:

[jamelang @虎克〜] $尾的/ etc /紅帽釋放
紅帽企業Linux服務器版本5.7(Tikanga)

我試過啓用核心轉儲ulimit -c unlimited但沒有文件出現。這是代碼,以註釋:

#include <cstdlib> 
#include <cstdio> 

#include <omp.h> 

int main() { 

    const unsigned int numberOfThreads = 12; 
    const unsigned int numberOfPartialSums = 30000; 
    const unsigned int numbersPerPartialSum = 40; 

    // make some numbers 
    srand(0); // every instance of program should get same results 
    const unsigned int totalNumbersToSum = numbersPerPartialSum * numberOfPartialSums; 
    double * inputData = new double[totalNumbersToSum]; 
    for (unsigned int index = 0; index < totalNumbersToSum; ++index) { 
    inputData[index] = rand()/double(RAND_MAX); 
    } 

    omp_set_num_threads(numberOfThreads); 

    // prepare a place to dump output 
    double * partialSums = new double[numberOfPartialSums]; 

    // do the following algorithm many times to induce a problem 
    for (unsigned int repeatIndex = 0; repeatIndex < 100000; ++repeatIndex) { 
    if (repeatIndex % 1000 == 0) { 
     printf("Absurd testing is on repeat %06u\n", repeatIndex); 
    } 

#pragma omp parallel for 
    for (unsigned int partialSumIndex = 0; partialSumIndex < numberOfPartialSums; 
     ++partialSumIndex) { 
     // get this partial sum's limits 
     const unsigned int beginIndex = numbersPerPartialSum * partialSumIndex; 
     const unsigned int endIndex = numbersPerPartialSum * (partialSumIndex + 1); 
     // we just sum the 40 numbers, can't get much simpler 
     double sumOfNumbers = 0; 
     for (unsigned int index = beginIndex; index < endIndex; ++index) { 
     // only reading, thread-safe 
     sumOfNumbers += inputData[index]; 
     } 
     // writing to non-overlapping indices (guaranteed by omp), 
     // should be thread-safe. 
     // at worst we would have false sharing, but that would just affect 
     // performance, not throw sigabrts. 
     partialSums[partialSumIndex] = sumOfNumbers; 
    } 
    } 

    delete[] inputData; 
    delete[] partialSums; 
    return 0; 
} 

我用下面的編譯:

/home/jamelang/gcc-4.8.1/bin/g++ -O3 -Wall -fopenmp殺手。 CC -o殺手

這似乎是鏈接到的正確共享對象:

[[email protected] Killer]$ ldd Killer 
    linux-vdso.so.1 => (0x00007fffc0599000) 
    libstdc++.so.6 => /home/jamelang/gcc-4.8.1/lib64/libstdc++.so.6 (0x00002b155b636000) 
    libm.so.6 => /lib64/libm.so.6 (0x0000003293600000) 
    libgomp.so.1 => /home/jamelang/gcc-4.8.1/lib64/libgomp.so.1 (0x00002b155b983000) 
    libgcc_s.so.1 => /home/jamelang/gcc-4.8.1/lib64/libgcc_s.so.1 (0x00002b155bb92000) 
    libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003293a00000) 
    libc.so.6 => /lib64/libc.so.6 (0x0000003292e00000) 
    /lib64/ld-linux-x86-64.so.2 (0x0000003292a00000) 
    librt.so.1 => /lib64/librt.so.1 (0x0000003298600000) 

一些注意事項:
1.在使用gcc 4.7的osx lion上,此代碼將拋出一個SIGABRT,類似於此問題:Why is this code giving SIGABRT with openMP?。使用gcc 4.8似乎解決了OSX上的問題。但是,在RHEL5機器上使用gcc 4.8並不能解決問題。 RHEL5機器有GLIBC版本2.5,似乎yum沒有提供更高版本,所以管理員堅持2.5。
2.如果我定義了一個SIGABRT信號處理程序,它不會在RHEL5機器上發現問題,但它確實在OSX上用gcc47捕獲它。
3.我相信不需要在omp子句中共享變量,因爲它們都可以有私有副本,但將它們添加爲共享不會改變行爲。
4.無論使用哪種優化級別,都會發生節點查殺。
5.即使我在gdb中運行程序(即在pbs文件中放入「gdb -batch -x gdbCommands Killer」),也會發生節點死亡,其中「gdbCommands」是一行文件:「run」
6.這個例子在每次重複時產生線程。一種策略是製作一個包含重複循環的並行塊,以防止出現這種情況。然而,這並不能幫助我 - 這個例子只代表了一個更大的研究代碼,我不能使用這個策略。

我完全沒有想法,在我最後一根稻草,在我的機智的結尾,準備把我的頭髮拉出來,等等。有沒有人有任何建議或意見?

+0

GCC的OpenMP運行時'libgomp'實現了一個線程池,因此在連續進入並行區域時不會產生新線程。但它可能是'libgomp'中的內存泄漏。它也在OS X上崩潰意味着問題不是GLIBC特定的。崩潰總是發生在相同的迭代數量附近嗎? –

+0

在相同的迭代編號中不會發生崩潰。超過90%的相同運行完成沒問題,其他運行崩潰,隨機地點,但幾乎總是在少數迭代。 –

回答

0

您正嘗試並行化嵌套for循環,在這種情況下,您需要將內部循環中的變量設置爲private,以便每個線程都有自己的變量。可以使用private子句完成,如下例所示。

#pragma omp parallel for private(j) 
for (i = 0; i < height; i++) 
for (j = 0; j < width; j++) 
    c[i][j] = 2; 

在你的情況,indexsumOfNumbers需要是私有的。

+0

恭敬地,我不認爲這是正確的。 'sumOfNumbers'和'index'都在'omp parallel for'塊的範圍內聲明,它們自動是私有的。此外,我不能將'private(sumOfNumbers)'添加到編譯指示語句中 - 尚未聲明!你同意嗎? –

+0

我的不好,是的他們默認是私人的。 – shrm

+0

沒問題!我很感激幫助的意願。 –