質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.34%
MPI

MPIは、並列プログラミングを利用するための標準化規格、及び実装自体のことを指します。バイト列で構成されたメッセージとして、いくつかのCPUが情報を送受信することにより協調動作を可能にします。

NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

1回答

944閲覧

Python3-numpy、32bit版と64bit版のdtype=objectのarrayの違いについて

gejisaki

総合スコア35

MPI

MPIは、並列プログラミングを利用するための標準化規格、及び実装自体のことを指します。バイト列で構成されたメッセージとして、いくつかのCPUが情報を送受信することにより協調動作を可能にします。

NumPy

NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2022/03/24 18:59

編集2022/03/24 22:19

32bit CPUと64bit CPUが混在するmpiクラスタを作成しました。
Linux上で、openmpi,Python3-mpi4pyを使っています。

32bitと64bitが混在できるよう、mpirunは./configureにて—enable-heterogeneousオプションをつけてビルドし、
mpirun —hostfile hostlist64bit python3 hello.py : —hostfile hostlist32bit python3 hello.py
にて、 いわゆるハローワールドが動作するところまでは確認できました。

次に円周率を計算しようと思ったのですが、どうもcomm.sendとcomm.recvにおけるnp.array(dtype=object)のやりとりに起因してエラーが発生しているようです。
クラスタの構造は2分木転送方式であり、broadcastやreduceは使っていません。

ちなみに、hostlistに64bitPCのみ、32bitPCのみを指定した場合は円周率がうまく計算できるので、
32bitノードと64bitノードがデータをやりとりする時に問題が起こっている可能性が高いと思います。

np.array作成時にdtype=int32などと指定すると混在でもうまくいくのですが、桁数を増やすためには、桁数制限のないobject型を使う必要があります。

numpyのobject型は、32bit版と64bit版で仕様が違うのでしょうか。

ご教示いただけますと幸いです。
よろしくお願いいたします。

<円周率計算プログラムの情報>

実行コマンド:
$mpirun --hostfile host64 -n 14 python3 pi_chudnovsky.py 13 : --hostfile host32 -n 2 python3 pi_chudnovsky.py 13
↑ちなみに、13のところを12以下にするとエラーなく実行できます。

pi_chudnovsky.pyについて:
https://github.com/kemusiro/openmpi-sample/からダウンロード
ライセンス
MIT License

Copyright (c) 2021 Kenichi Miyata

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

コード本文

python

1from mpi4py import MPI 2import gmpy2 as mp 3from gmpy2 import mpz 4import numpy as np 5import mmap 6import sys 7import os 8 9# 円周率を並列に計算する。 10def calc_PQT_root(n): 11 # まず自分の割り当て分を計算する。 12 alloc = int(n / size) 13 PQT2 = calc_PQT_local(rank * alloc, (rank + 1) * alloc) 14 15 # 各ノードの計算結果をマージする。 16 level = int(mp.ceil(mp.log2(size))) 17 k = 1 18 for _ in range(level): 19 if (rank & k) == k: 20 PQT1 = comm.recv(source=rank-k, tag=0) 21 PQT2 = np.array([PQT1[0] * PQT2[0], 22 PQT1[1] * PQT2[1], 23 PQT1[2] * PQT2[1] + PQT1[0] * PQT2[2]]) 24 k *= 2 25 else: 26 comm.send(PQT2, dest=rank+k, tag=0) 27 break 28 return PQT2 29 30# ノード内でP(n1, n2), Q(n1, n2), T(n1, n2)を計算する。 31def calc_PQT_local(n1, n2): 32 if n1 + 1 == n2: 33 P = mpz((-1) * (2 * n2 - 1) * (6 * n2 - 5) * (6 * n2 - 1)) 34 return np.array([P, C3over24 * n2 ** 3, (A + B * n2) * P]) 35 else: 36 m = int((n1 + n2) / 2) 37 PQT1 = calc_PQT_local(n1, m) 38 PQT2 = calc_PQT_local(m, n2) 39 return np.array([PQT1[0] * PQT2[0], 40 PQT1[1] * PQT2[1], 41 PQT1[2] * PQT2[1] + PQT1[0] * PQT2[2]]) 42 43# 円周率が何桁まで一致するかを判定する。 44def check_pi(outfile, pifile): 45 with open(pifile, 'rb') as f0, \ 46 open(outfile, 'rb') as f1: 47 # 2つのファイルをメモリにマップして比較する。 48 with mmap.mmap(f0.fileno(), 0, flags=mmap.MAP_PRIVATE) as mm0, \ 49 mmap.mmap(f1.fileno(), 0, flags=mmap.MAP_PRIVATE) as mm1: 50 index = mpz(0) 51 length = 1024 * 1024 # 一度にチェックする桁数 52 found = False 53 while not found: 54 ans = mm0.read(length) 55 calc = mm1.read(length) 56 if ans != calc: 57 maxlen = min(len(ans), len(calc)) 58 for i in range(maxlen): 59 if ans[i] != calc[i]: 60 n = index + i - 2 61 found = True 62 break 63 else: 64 n = index + maxlen - 3 65 break 66 else: 67 index += length 68 return n 69 70if __name__ == '__main__': 71 comm = MPI.COMM_WORLD 72 rank = comm.Get_rank() 73 size = comm.Get_size() 74 75 if len(sys.argv) < 2: 76 if rank == size - 1: 77 print('python3 pi_chudnovsky.py <power> [pifile]') 78 sys.exit(0) 79 80 if not sys.argv[1].isdecimal(): 81 if rank == size - 1: 82 print('not decimal value: {}'.format(sys.argv[1])) 83 print('python3 pi_chudnovsky.py power [pifile]') 84 sys.exit(0) 85 power = int(sys.argv[1]) 86 87 if len(sys.argv) == 2: 88 pifile = '/share/common/pi-10oku.txt' 89 else: 90 pifile = sys.argv[2] 91 if not os.path.exists(pifile): 92 if rank == size - 1: 93 print('{} does not exist'.format(pifile)) 94 print('python3 pi_chudnovsky.py <power> [pifile]') 95 sys.exit(0) 96 outfile = 'pi.txt' 97 98 A = mpz(13591409) 99 B = mpz(545140134) 100 C = mpz(640320) 101 C3over24 = mpz(C**3 / 24) 102 103 n = 2 ** power 104 digits = n * 14 105 # gmpy2の浮動小数の精度として、求められる円周率の桁数を設定する。 106 mp.get_context().precision = int(digits * mp.log2(10)) 107 108 if rank == size - 1: 109 print('calculating...') 110 start = MPI.Wtime() 111 PQT = calc_PQT_root(n) 112 if rank == size - 1: 113 temp1 = C * mp.sqrt(C) * PQT[1] 114 temp2 = 12 * (PQT[2] + A * PQT[1]) 115 pi = temp1 / temp2 116 end = MPI.Wtime() 117 with open(outfile, 'w') as f: 118 f.write(str(pi)) 119 print('checking...') 120 n = check_pi(outfile, pifile) 121 print('time = {:.2f} sec.'.format(end - start)) 122 print(f'match = {n}')

出力:
… 途中省略 …
calculating...
[debian10:08494] *** Process received signal ***
[debian10:08494] Signal: Segmentation fault (11)
[debian10:08494] Signal code: (128)
[debian10:08494] Failing at address: (nil)
[debian10:08494] [ 0] /lib/x86_64-linux-gnu/libpthread.so.0(+0x14140)[0x7fc4662bc140]
[debian10:08494] [ 1] /usr/local/lib/openmpi/mca_pml_ob1.so(mca_pml_ob1_send_request_put+0x17)[0x7fc45f6f6a87]
[debian10:08494] [ 2] /usr/local/lib/openmpi/mca_btl_tcp.so(+0x9087)[0x7fc4640b5087]
[debian10:08494] [ 3] /usr/local/lib/libopen-pal.so.40(opal_libevent2022_event_base_loop+0x697)[0x7fc4657c6247]
[debian10:08494] [ 4] /usr/local/lib/libopen-pal.so.40(+0x37256)[0x7fc46577f256]
[debian10:08494] [ 5] /usr/local/lib/libopen-pal.so.40(opal_progress+0x84)[0x7fc46577f3a4]
[debian10:08494] [ 6] /usr/local/lib/libopen-pal.so.40(ompi_sync_wait_mt+0xb5)[0x7fc4657859b5]
[debian10:08494] [ 7] /usr/local/lib/openmpi/mca_pml_ob1.so(mca_pml_ob1_send+0x1292)[0x7fc45f6e6b82]
[debian10:08494] [ 8] /usr/local/lib/libmpi.so.40(PMPI_Send+0x11b)[0x7fc46599372b]
[debian10:08494] [ 9] /usr/lib/python3/dist-packages/mpi4py/MPI.cpython-39-x86_64-linux-gnu.so(+0xe45b8)[0x7fc465b155b8]
[debian10:08494] [10] python3[0x53f350]
[debian10:08494] [11] python3(_PyObject_MakeTpCall+0x39b)[0x51d89b]
[debian10:08494] [12] python3(_PyEval_EvalFrameDefault+0x5f7f)[0x517a0f]
[debian10:08494] [13] python3(_PyFunction_Vectorcall+0x1a3)[0x528b63]
[debian10:08494] [14] python3(_PyEval_EvalFrameDefault+0x525)[0x511fb5]
[debian10:08494] [15] python3[0x5106ed]
[debian10:08494] [16] python3(_PyEval_EvalCodeWithName+0x47)[0x510497]
[debian10:08494] [17] python3(PyEval_EvalCode+0x23)[0x5f5be3]
[debian10:08494] [18] python3[0x619de7]
[debian10:08494] [19] python3[0x615610]
[debian10:08494] [20] python3[0x619d79]
[debian10:08494] [21] python3(PyRun_SimpleFileExFlags+0x196)[0x619816]
[debian10:08494] [22] python3(Py_RunMain+0x2b3)[0x60d4e3]
[debian10:08494] [23] python3(Py_BytesMain+0x29)[0x5ea6e9]
[debian10:08494] [24] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xea)[0x7fc465f6cd0a]
[debian10:08494] [25] python3(_start+0x2a)[0x5ea5ea]
[debian10:08494] *** End of error message ***

Primary job terminated normally, but 1 process returned
a non-zero exit code. Per user-direction, the job has been aborted.


mpirun noticed that process rank 7 with PID 8494 on node 192.168.10.128 exited on signal 11 (Segmentation fault).

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

gejisaki

2022/03/24 19:46 編集

出力されたエラー内容を追記させていただきます。 プログラムについては雑誌に掲載のサンプルプログラムであるため、著作権の関係上すべて掲載できません。 申し訳ありません。 ただ、質問本文にも記載させていただきましたとおり、おそらく、エラーの原因はMPIにおけるcomm.send,comm.recvが32bitPCと64bitPC間でなされるときに起こっているであることは推定できています。(クラスタの構造は2分木転送方式であり、broadcastやreduceは使っていません。) コマンド: $ mpirun --hostfile hostlist64bit python3 calc_pi.py : --hostfile hostlist32bit python3 calc_pi.py 出力: … 途中省略 … calculating...    ←この行のみプログラムの出力です。 [debian10:08494] *** Process received signal *** [debian10:08494] Signal: Segmentation fault (11) [debian10:08494] Signal code: (128) [debian10:08494] Failing at address: (nil) [debian10:08494] [ 0] /lib/x86_64-linux-gnu/libpthread.so.0(+0x14140)[0x7fc4662bc140] [debian10:08494] [ 1] /usr/local/lib/openmpi/mca_pml_ob1.so(mca_pml_ob1_send_request_put+0x17)[0x7fc45f6f6a87] [debian10:08494] [ 2] /usr/local/lib/openmpi/mca_btl_tcp.so(+0x9087)[0x7fc4640b5087] [debian10:08494] [ 3] /usr/local/lib/libopen-pal.so.40(opal_libevent2022_event_base_loop+0x697)[0x7fc4657c6247] [debian10:08494] [ 4] /usr/local/lib/libopen-pal.so.40(+0x37256)[0x7fc46577f256] [debian10:08494] [ 5] /usr/local/lib/libopen-pal.so.40(opal_progress+0x84)[0x7fc46577f3a4] [debian10:08494] [ 6] /usr/local/lib/libopen-pal.so.40(ompi_sync_wait_mt+0xb5)[0x7fc4657859b5] [debian10:08494] [ 7] /usr/local/lib/openmpi/mca_pml_ob1.so(mca_pml_ob1_send+0x1292)[0x7fc45f6e6b82] [debian10:08494] [ 8] /usr/local/lib/libmpi.so.40(PMPI_Send+0x11b)[0x7fc46599372b] [debian10:08494] [ 9] /usr/lib/python3/dist-packages/mpi4py/MPI.cpython-39-x86_64-linux-gnu.so(+0xe45b8)[0x7fc465b155b8] [debian10:08494] [10] python3[0x53f350] [debian10:08494] [11] python3(_PyObject_MakeTpCall+0x39b)[0x51d89b] [debian10:08494] [12] python3(_PyEval_EvalFrameDefault+0x5f7f)[0x517a0f] [debian10:08494] [13] python3(_PyFunction_Vectorcall+0x1a3)[0x528b63] [debian10:08494] [14] python3(_PyEval_EvalFrameDefault+0x525)[0x511fb5] [debian10:08494] [15] python3[0x5106ed] [debian10:08494] [16] python3(_PyEval_EvalCodeWithName+0x47)[0x510497] [debian10:08494] [17] python3(PyEval_EvalCode+0x23)[0x5f5be3] [debian10:08494] [18] python3[0x619de7] [debian10:08494] [19] python3[0x615610] [debian10:08494] [20] python3[0x619d79] [debian10:08494] [21] python3(PyRun_SimpleFileExFlags+0x196)[0x619816] [debian10:08494] [22] python3(Py_RunMain+0x2b3)[0x60d4e3] [debian10:08494] [23] python3(Py_BytesMain+0x29)[0x5ea6e9] [debian10:08494] [24] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xea)[0x7fc465f6cd0a] [debian10:08494] [25] python3(_start+0x2a)[0x5ea5ea] [debian10:08494] *** End of error message *** -------------------------------------------------------------------------- Primary job terminated normally, but 1 process returned a non-zero exit code. Per user-direction, the job has been aborted. -------------------------------------------------------------------------- -------------------------------------------------------------------------- mpirun noticed that process rank 7 with PID 8494 on node 192.168.10.128 exited on signal 11 (Segmentation fault). --------------------------------------------------------------------------
gejisaki

2022/03/24 20:07

プログラムのライセンスを改めて確認したところ、配布可能だったので、プログラムの全文を載せます。 よろしくおねがいします。 from mpi4py import MPI import gmpy2 as mp from gmpy2 import mpz import numpy as np import mmap import sys import os # 円周率を並列に計算する。 def calc_PQT_root(n): # まず自分の割り当て分を計算する。 alloc = int(n / size) PQT2 = calc_PQT_local(rank * alloc, (rank + 1) * alloc) # 各ノードの計算結果をマージする。 level = int(mp.ceil(mp.log2(size))) k = 1 for _ in range(level): if (rank & k) == k: PQT1 = comm.recv(source=rank-k, tag=0) PQT2 = np.array([PQT1[0] * PQT2[0], PQT1[1] * PQT2[1], PQT1[2] * PQT2[1] + PQT1[0] * PQT2[2]]) k *= 2 else: comm.send(PQT2, dest=rank+k, tag=0) break return PQT2 # ノード内でP(n1, n2), Q(n1, n2), T(n1, n2)を計算する。 def calc_PQT_local(n1, n2): if n1 + 1 == n2: P = mpz((-1) * (2 * n2 - 1) * (6 * n2 - 5) * (6 * n2 - 1)) return np.array([P, C3over24 * n2 ** 3, (A + B * n2) * P]) else: m = int((n1 + n2) / 2) PQT1 = calc_PQT_local(n1, m) PQT2 = calc_PQT_local(m, n2) return np.array([PQT1[0] * PQT2[0], PQT1[1] * PQT2[1], PQT1[2] * PQT2[1] + PQT1[0] * PQT2[2]]) # 円周率が何桁まで一致するかを判定する。 def check_pi(outfile, pifile): with open(pifile, 'rb') as f0, \ open(outfile, 'rb') as f1: # 2つのファイルをメモリにマップして比較する。 with mmap.mmap(f0.fileno(), 0, flags=mmap.MAP_PRIVATE) as mm0, \ mmap.mmap(f1.fileno(), 0, flags=mmap.MAP_PRIVATE) as mm1: index = mpz(0) length = 1024 * 1024 # 一度にチェックする桁数 found = False while not found: ans = mm0.read(length) calc = mm1.read(length) if ans != calc: maxlen = min(len(ans), len(calc)) for i in range(maxlen): if ans[i] != calc[i]: n = index + i - 2 found = True break else: n = index + maxlen - 3 break else: index += length return n if __name__ == '__main__': comm = MPI.COMM_WORLD rank = comm.Get_rank() size = comm.Get_size() if len(sys.argv) < 2: if rank == size - 1: print('python3 pi_chudnovsky.py <power> [pifile]') sys.exit(0) if not sys.argv[1].isdecimal(): if rank == size - 1: print('not decimal value: {}'.format(sys.argv[1])) print('python3 pi_chudnovsky.py power [pifile]') sys.exit(0) power = int(sys.argv[1]) if len(sys.argv) == 2: pifile = '/share/common/pi-10oku.txt' else: pifile = sys.argv[2] if not os.path.exists(pifile): if rank == size - 1: print('{} does not exist'.format(pifile)) print('python3 pi_chudnovsky.py <power> [pifile]') sys.exit(0) outfile = 'pi.txt' A = mpz(13591409) B = mpz(545140134) C = mpz(640320) C3over24 = mpz(C**3 / 24) n = 2 ** power digits = n * 14 # gmpy2の浮動小数の精度として、求められる円周率の桁数を設定する。 mp.get_context().precision = int(digits * mp.log2(10)) if rank == size - 1: print('calculating...') start = MPI.Wtime() PQT = calc_PQT_root(n) if rank == size - 1: temp1 = C * mp.sqrt(C) * PQT[1] temp2 = 12 * (PQT[2] + A * PQT[1]) pi = temp1 / temp2 end = MPI.Wtime() with open(outfile, 'w') as f: f.write(str(pi)) print('checking...') n = check_pi(outfile, pifile) print('time = {:.2f} sec.'.format(end - start)) print(f'match = {n}')
gejisaki

2022/03/24 20:10

プログラムのライセンス情報 MIT License Copyright (c) 2021 Kenichi Miyata Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. https://github.com/kemusiro/openmpi-sample/からダウンロード
y_waiwai

2022/03/24 22:02

質問文は編集できますんでそっちに提示しよう
gejisaki

2022/03/24 22:17

申し訳ありません。 質問本文に記載させていただきました。
bsdfan

2022/03/29 01:22 編集

(勘違いのコメントだっため削除)
guest

回答1

0

あくまで想像ですが,numpyのobjectの中身は

  • データ型や名前等の情報
  • 実際のデータを格納している領域
  • データを格納している領域への参照情報(C言語でいうポインタ)

を含んでいて,この「参照情報」の部分が32bit,64bitでサイズが違っていて
このやり取りの時にセグメンテーションフォールトが発生しているのではないかと思います。

32bitのWindowsでは2GBしかメモリが使えないとか,32bitのLinuxでは1プロセス4GBまで等の制限は
32bit でメモリ上のアドレスを表現していたことによるもので,64bit OSではこの部分が64bitで
サイズが倍になっており,この部分が不整合につながりやすいのではと思います。

投稿2023/05/31 11:43

ujimushi_sradjp

総合スコア2157

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.34%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問