Pergunta

Primeira vez usando o MPI fora de alguns aplicativos de prática simples, e algo não está indo bem.

Eu tenho uma classe definida com os seguintes membros (métodos omitidos por uma questão de legibilidade e conservação de espaço na tela):

class particle
{
    public:
        double _lastUpdate;
    float _x, _y, _xvel, _yvel;
    bool _isStatic;
        bool _isForeign;
        float _size;

    private:
        int _isStaticInt;           // integer copy of _isStatic to be sent over MPI ( since there's no MPI_BOOL :C )
};

Quero enviar conjuntos de partículas entre os processos enviando os valores de alguns membros -chave de cada partícula e replicando os outros no local. Para esse fim, defino um tipo de dados MPI como tal; Como você pode ver, os membros _Lastupdate, _isstatic e _isforeign não estão incluídos:

MPI_Datatype types[] = { MPI_FLOAT, MPI_FLOAT, MPI_FLOAT, MPI_FLOAT, MPI_INTEGER, MPI_FLOAT };
std::vector<int> len(6, 1);
std::vector<MPI_Aint> disp(6, 0);
particle temp;
MPI_Aint base;
MPI_Address(&temp, &base);
MPI_Address(&temp._x, &disp[0]);
MPI_Address(&temp._y, &disp[1]);
MPI_Address(&temp._xvel, &disp[2]);
MPI_Address(&temp._yvel, &disp[3]);
MPI_Address(&temp._isStaticInt, &disp[4]);
MPI_Address(&temp._size, &disp[5]);
for (int i=0; i<6; ++i)
{
    disp[i] = disp[i] - base;
}
MPI_Type_struct(6, &len[0], &disp[0], types, &_particleType);
MPI_Type_commit(&_particleType);

É assim que envio as partículas; 'partes' é um vetor de partícula* que contém ponteiros para os objetos de partícula que quero enviar e 'tamanho' é parte.size ().

std::vector<int> len(size, 1);
std::vector<MPI_Aint> disp(size, 0);
MPI_Aint base;
MPI_Address(parts[0], &base);                   // datatype begins at the first selected object
for (int select = 1; select < size; ++select)
{
    MPI_Address(parts[select], &disp[select]);
    disp[select] = disp[select] - base;
}
MPI_Type_hindexed(size, &len[0], &disp[0], _particleType, &_sendType);
MPI_Type_commit(&_sendType);

MPI_Request payload_req;
MPI_Isend(parts[0], 1, _sendType, ngb, 0, _cartesian_comm, &payload_req);

O recebimento acontece da mesma forma, apenas neste caso, 'partes' é um vetor de partícula* que aponta para objetos de partículas "em branco" criados anteriormente, cujos membros devem ser preenchidos com os dados que recebemos:

std::vector<int> len(size, 1);
std::vector<MPI_Aint> disp(size, 0);
MPI_Aint base;
MPI_Address(parts[0], &base);                       // datatype begins at the first newly inserted object
for (int part = 1; part < size; ++part)
{
    MPI_Address(parts[part], &disp[part]);
    disp[part] = disp[part] - base;
}
MPI_Type_hindexed(size, &len[0], &disp[0], _particleType, &_recvType);
MPI_Type_commit(&_recvType);
MPI_Status status;
MPI_Recv(parts[0], size, _particleType, ngb, 0, _cartesian_comm, &status);

O problema é que todas as partículas recebidas, exceto a primeira, têm os valores "em branco" padrão em seus membros. Eu escrevi um pequeno aplicativo de teste antes que fizesse algo semelhante, e funcionou perfeitamente, embora apenas transmitisse alguns valores simples. Isso me leva a acreditar que, a menos que haja um erro de codificação que eu não percebi aqui (totalmente possível), esse tipo de truque do tipo de dados não é garantido para funcionar, e o pouco que funciona o faz apenas por acidente.

Alguém pode confirmar/negar se esse tipo de manipulação de memória é seguro e deve ser confiado?

Foi útil?

Solução

Não importa, parece que simplesmente digitar a pergunta me fez perceber o que está errado.

O comando de recebimento deve ser:

MPI_Recv(parts[0], 1, _recvType, ngb, 0, _cartesian_comm, &status);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top