0

MPI を使用する古くて厄介な Fortran プログラムがあります。malloc()C で記述された小さなモジュールが 1 つあり、が返されるまで繰り返し呼び出してメモリ内の最大の割り当て可能なブロックを決定しようとしnull、次に成功した最大の割り当てサイズを Fortran プログラムに返します。

を使用してコンパイルするとgfortranうまく動作しますが、 を使用しようとするmpif90と、最後malloc()に を返す代わりに segfault が発生しnullます。

これは、実際の MPI コードを含まない最小の例です。ファイルmain.f:

program test
    complex(8) :: sig(256000000) ! Just allocating some big array in fortran
    sig(1) = 0.d0                ! and now wondering how much space is left?
    call bigalloc
end

ファイルbigalloc.c

#include <stdlib.h>
#include <stdio.h>

void bigalloc_() {
    size_t step = 0x80000000;
    size_t size = 0;
    int failed = 0;
    void* p;
    do {
        size += step;
        p = malloc(size);
        if (p) {
            free(p);
            printf("Allocated %zd...\n", size);
        } else {
            printf("So, that's our limit\n");
            failed = 1;
        }
    } while (!failed);
}

以下を使用してコンパイルおよび実行しますgfortran(期待どおりに動作します):

~$ gcc -c bigalloc.c -o bigalloc.o && gfortran -o main main.f bigalloc.o && ./main
Allocated 2147483648...
Allocated 4294967296...
So, that's our limit

MPI でコンパイルして実行 (失敗):

~$ gcc -c bigalloc.c -o bigalloc.o && mpif90 -o main main.f bigalloc.o && ./main
Allocated 2147483648...
Allocated 4294967296...
Segmentation fault

gccここで何も変更しないで置き換えmpiccます。mainも C で書かれ、mpiccすべてを使用してコンパイルされる場合も OK です。したがって、問題は Fortran だけです。

の出力mpif90 -showはこちらです。問題は、オプションの存在のみに依存し-lopen-palます。

$ mpif90 -show
gfortran -I/usr/include/openmpi/1.2.4-gcc/64 -I/usr/include/openmpi/1.2.4-gcc -m64 -pthread -I/usr/lib64/openmpi/1.2.4-gcc -L/usr/lib64/openmpi/1.2.4-gcc -lmpi_f90 -lmpi_f77 -lmpi -lopen-rte -lopen-pal -ldl -Wl,--export-dynamic -lnsl -lutil -lm -ldl

MPI をリンクしている間、stnadardmallocを PAL からの独自の stnadard に置き換えているようですが、これは例外では適切に機能しません。bigalloc.cそれを回避する方法はありますか (たとえば、myをglibc静的にリンクするなど)?

4

1 に答える 1

0

Open MPI は、 が提供するフック メカニズムを介してインターセプトmalloc()およびfree()呼び出しを行い、動的に割り当てられたバッファーと割り当て解除されたバッファーを追跡できるようにします。glibcこれは、InfiniBand のような RDMA ベースのネットワークでは、ハードウェアがアクセスできるように、通信バッファーを物理メモリに固定する (移動できないようにする) 必要があるためです。メモリの登録と登録解除 (固定および固定解除のプロセス) にはかなりの時間がかかります。そのため、ライブラリは、再利用されることを期待して、既に固定されているメモリの固定を解除しません (そのため、各通信バッファーを動的に割り当てることは非常に重要です)。悪いアイデア)。ただし、メモリが動的に割り当てられ、登録されてから割り当て解除されると、問題が発生する可能性があります。そのため、Open MPI はmalloc/freeAPI を使用して動的割り当てを追跡します。Open MPI は、ハードウェアがサポートしており、ライブラリがそれに応じてビルドされている場合、MMU 通知を使用してメモリを追跡することもできます。

メモリ フックは、少なくとも新しい Open MPI リリースでは、memory_linux_disableMCA パラメータを に設定することで無効にすることができます1。他のすべての MCA 変数とは異なり、これは環境を介してのみ設定できます。たとえば、環境変数OMPI_MCA_memory_linux_disableを設定し1てエクスポートする必要があります。プログラムが InfiniBand またはその他の RDMA ベースのネットワークを使用するクラスターで実行される場合は、これを行わないでください。残念ながら、この MCA パラメーターを認識しない古いバージョンの Open MPI を実行しており、memory_hooksモジュールはそれを無効にするメカニズムを提供していないようです。Open MPI Usersメーリング リストで質問してください。

また、Linux カーネルはデフォルトでメモリをオーバーコミットすることに注意してください。つまり、物理メモリ サイズを超える仮想メモリ割り当てを許可します。最終的な結果としてmalloc()、利用可能な物理メモリ サイズよりもはるかに大きなメモリ サイズで成功しますが、ユーザー (または任意の Open MPI フック プロシージャ) がそのメモリを使用しようとすると、ある時点で物理メモリが枯渇し、プロセスはSIGSEGV.

于 2013-04-10T14:39:05.850 に答える