3

電気柵を使用して、私のプログラムでいくつかのメモリエラーを見つけようとしています。私のプログラムは OpenMPI を使用しており、それを実行しようとすると、次のバック トレースでセグメンテーション違反が発生します。

Program received signal SIGSEGV, Segmentation fault.
2001    ../sysdeps/x86_64/multiarch/memcpy-ssse3-back.S: No such file or directory.
__memcpy_ssse3_back () at ../sysdeps/x86_64/multiarch/memcpy-ssse3-back.S:2001
(gdb) bt
#0  __memcpy_ssse3_back ()
    at ../sysdeps/x86_64/multiarch/memcpy-ssse3-back.S:2001
#1  0x00007ffff72d6b7f in ompi_ddt_copy_content_same_ddt ()
   from /usr/lib/libmpi.so.0
#2  0x00007ffff72d4d0d in ompi_ddt_sndrcv () from /usr/lib/libmpi.so.0
#3  0x00007ffff72dd5b3 in PMPI_Allgather () from /usr/lib/libmpi.so.0
#4  0x00000000004394f1 in ppl::gvec<unsigned int>::gvec (this=0x7fffffffdd60, 
    length=1) at qppl/gvec.h:32
#5  0x0000000000434a35 in TreeBuilder::TreeBuilder (this=0x7fffffffdc60, 
    octree=..., mygbodytab=..., mylbodytab=..., cellpool=0x7fffef705fc8, 
---Type <return> to continue, or q <return> to quit---
    leafpool=0x7fffef707fc8, bodypool=0x7fffef6bdfc0) at treebuild.cxx:93
#6  0x000000000042fb6b in BarnesHut::BuildOctree (this=0x7fffffffde50)
    at barnes.cxx:155
#7  0x000000000042af52 in BarnesHut::Run (this=0x7fffffffde50)
    at barnes.cxx:386
#8  0x000000000042b164 in main (argc=1, argv=0x7fffffffe118) at barnes.cxx:435

私のコードの関連部分は次のとおりです。

   me = spr_locale_id();
   world_size = spr_num_locales();
   my_elements = std::shared_ptr<T>(new T[1]);

   world_element_pointers = std::shared_ptr<T*>(new T*[world_size]);

   MPI_Allgather(my_elements.get(), sizeof(T*), MPI_BYTE,
       world_element_pointers.get(), sizeof(T*), MPI_BYTE,
       MPI_COMM_WORLD);

__memcpy_ssse3_back がセグメンテーション違反を引き起こしている理由がわかりません。プログラムのこの部分は、電気柵なしで実行してもセグメンテーション フォールトしません。誰が何が起こっているのか知っていますか?私はopenmpiバージョン1.4.3を使用しています

4

1 に答える 1

4

このエラーには、次の 2 つの理由が考えられます。

古い Open MPI バージョンに存在するデータ コピー ルーチンにバグがあり、バージョン 1.4.4 で修正されたようです。この場合、Open MPI ライブラリを新しいバージョンにアップグレードすると問題が解決します。

別の考えられる理由はmy_elements、タイプ の単一アイテムの配列ですT。呼び出しでは、MPI_Allgatherこの要素へのポインターを渡しますが、代わりsizeof(T*)に送信するバイト数を指定します。デフォルトでは、Electric Fence は新しく割り当てられたメモリをメモリ ページの最後に配置し、その直後にアクセスできないメモリ ページを挿入します。Tたまたまポインター型よりも短い場合 (たとえば、 64 ビットの LP64 プラットフォームで実行してTいるint場合)、アクセスできないメモリ ページへのアクセスが発生し、セグメンテーション フォールトが発生します。あなたの意図は実際にデータへのポインターを送信することであるため、代わりにMPI_Allgather返された値へのポインターを渡す必要がありますmy_elements.get()

ところで、ポインターを渡すのは良いことではありません。MPI は、独自の移植可能な RDMA 実装を提供します。MPI 標準の片側通信の章を参照してください。少し面倒ですが、少なくとも移植可能であるべきです。

于 2013-01-21T09:45:36.227 に答える