Несоответствие кода Python при сложном умножении в MPI - PullRequest
0 голосов
/ 22 мая 2018

Предположим, что программа Python MPI, где главный узел отправляет пару сложных матриц каждому рабочему узлу, а рабочий узел должен вычислять свой продукт (обычный матричный продукт).Входные матрицы строятся в главном узле в соответствии с некоторым алгоритмом, который не нужно объяснять.Теперь представьте для простоты, что у нас есть только 2 MPI-процесса, один мастер и один рабочий.Я создал две версии этой программы для этого случая.Первый создает два комплексных числа (матрицы 1 на 1 для простоты) и отправляет их работнику для вычисления продукта.Эта программа как скелет для того, что я пытаюсь сделать с несколькими работниками.Во второй программе я опустил алгоритм и просто жестко запрограммировал эти два комплексных числа в коде.Предполагается, что программы должны давать такой же продукт, как показано здесь:

a = 28534314.10478439+28534314.10478436j

b = -1.39818115e+09+1.39818115e+09j

a*b = -7.97922802e+16+48j

Это было проверено вMatlab.Вместо этого первая программа не работает, и работник выдает a*b = -7.97922801e+16+28534416.j, в то время как вторая программа работает правильно.Обратите внимание, что в обоих случаях данные корректно передаются от мастера к работнику (см. Функции print()).Первая (неправильная) программа:

from mpi4py import MPI
import numpy as np

N = 1
ell = 9
s_cod = 7
var = np.array([np.exp(1j*2*np.pi*1/8)])
comm = MPI.COMM_WORLD

if comm.rank == 0:

    print("I am sender")

    #Construction algorithm, explanation skipped
    A=np.matrix('1 0; 0 1')
    B=np.matrix('1 0; 0 1')
    Ah=np.split(A,2)
    Bh=np.split(B,2)
    Ahv = []
    Bhv = []
    for i in range(2):
        Ahv.append(np.split(Ah[i], 2, axis=1))
        Bhv.append(np.split(Bh[i], 2, axis=1))
    a = []
    b = []
    for i in range(N):
        a.append(Ahv[0][0]*(pow(s_cod*var[i], ell)) + Ahv[1][0] + Ahv[0][1]*(pow(s_cod*var[i], ell+1)) + Ahv[1][1]*s_cod*var[i])
        b.append(Bhv[0][0] + Bhv[1][0]*(pow(s_cod*var[i], ell)) + Bhv[0][1]*(pow(s_cod*var[i], 2)) + Bhv[1][1]*(pow(s_cod*var[i], ell+2)))

    #Send message with a predefined tag, like 15 and 16, to each receiver
    for i in range(N):
        comm.Isend([a[i],MPI.COMPLEX], dest=i+1, tag=15)
        comm.Isend([b[i],MPI.COMPLEX], dest=i+1, tag=16)

    print("Sender sent:  ")
    print(a[0])
    print(b[0])

else:

    print("I am receiver")

    A = np.empty_like(np.matrix([[0]*(1) for i in range(1)])).astype(np.complex128)
    B = np.empty_like(np.matrix([[0]*(1) for i in range(1)])).astype(np.complex128)

    #Receive message with tags 15, 16 from rank 0
    rA = comm.Irecv(A, source=0, tag=15)
    rB = comm.Irecv(B, source=0, tag=16)

    rA.wait()
    rB.wait()

    C = np.dot(A, B)

    print("Receiver received:  ")
    print(A)
    print(B)

    print("Receiver computed:  ")
    print(C)

Вторая (правильная) программа:

from mpi4py import MPI
import numpy as np

comm = MPI.COMM_WORLD

if comm.rank == 0:

    print("I am sender")

    a = np.matrix('28534314.10478439+28534314.10478436j')
    b = np.matrix('-1.39818115e+09+1.39818115e+09j')

    #Send message with a predefined tag, like 15 and 16, to rank 1
    comm.Isend([a, MPI.COMPLEX], dest=1, tag=15)
    comm.Isend([b, MPI.COMPLEX], dest=1, tag=16)

    print("Sender sent:  ")
    print(a[0])
    print(b[0])

else:

    print("I am receiver")

    A = np.empty_like(np.matrix([[0]*(1) for i in range(1)])).astype(np.complex128)
    B = np.empty_like(np.matrix([[0]*(1) for i in range(1)])).astype(np.complex128)

    #Receive message with tags 15, 16 from rank 0
    rA = comm.Irecv(A, source=0, tag=15)
    rB = comm.Irecv(B, source=0, tag=16)

    rA.wait()
    rB.wait()

    C = np.dot(A, B)

    print("Receiver received:  ")
    print(A)
    print(B)

    print("Receiver computed:  ")
    print(C)

Я использую MPI4py 3.0.0.вместе с Python 2.7.14 и ядром Open MPI 2.1.2.Я боролся с этой проблемой целый день и до сих пор не могу понять, что происходит.Я пробовал многочисленные инициализации, такие как np.zeros(), np.zeros_like(), np.empty_like(), а также np.array и np.matrix и функции np.dot(), np.matmul() и оператор *.Наконец, я думаю, что проблема всегда в мнимой части продукта, основанной на других примерах, которые я пробовал.Есть предложения?

1 Ответ

0 голосов
/ 24 мая 2018

Это совершенно не связано с MPI.

np.set_printoptions(precision=15)

Чтобы подтвердить, что вычисленные a и b на самом деле отличаются от тех, которые вы вводите в "правильную" версию.

Я не уверен, какова основная истина для результатов.Могут быть ошибки округления, влияние которых возрастает во время вычислений.Во время точечного произведения различия проявляются радикально, потому что в «правильной» версии абсолютные вещественные / мнимые части b равны, в вычисленной версии они только относительно близки, но существует значительная абсолютная разница.

...