MPI 사용자 정의 데이터 유형, 내가하고있는 일은 안전합니까?
-
19-09-2019 - |
문제
간단한 연습 앱 외부에서 MPI를 처음 사용하면 무언가가 제대로 진행되지 않습니다.
다음 멤버로 정의 된 수업이 있습니다 (가독성 및 화면 공간을 보존하기 위해 생략 된 방법) :
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 )
};
각 입자의 일부 핵심 멤버의 값을 보내고 다른 입자를 그 자리에서 복제하여 프로세스 간 입자 세트를 보내려고합니다. 이를 위해 MPI 데이터 타입을 정의합니다. 보시다시피, 회원 _lastupdate, _isstatic 및 _isforeign은 포함되지 않습니다.
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);
이것이 내가 입자를 보내는 방법입니다. '부품'은 내가 보내고 싶은 입자 물체에 대한 포인터를 포함하는 입자의 벡터*이며 'size'는 parts.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);
수신은 유사하게 발생합니다.이 경우에만 '부품'은 입자의 벡터입니다. 이는 이전에 생성 된 "빈"입자 물체를 가리키며, 멤버는 우리가받는 데이터로 채워져 있습니다.
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);
문제는 첫 번째 입자를 제외한 모든 입자가 멤버에 기본 "공백"값을 가지고 있다는 것입니다. 나는 그 전에 작은 테스트 앱을 썼다. 그로 인해 비슷한 일이 있었지만 몇 가지 간단한 값 만 전송했지만 완벽하게 작동했다. 이로 인해 코딩 실수가 없으면 여기에서 눈치 채지 못하는 경우 (전적으로 가능), 이런 종류의 데이터 유형의 속임수는 작동하는 것이 보장되지 않으며, 작동하는 작은 것은 우연히만 그렇게합니다.
이 유형의 메모리 조작이 안전하고 의존 해야하는지 확인/거부 할 수 있습니까?
해결책
신경 쓰지 마십시오. 단순히 질문을 입력하면 무엇이 잘못되었는지 깨달았습니다.
수신 명령은 다음과 같아야합니다.
MPI_Recv(parts[0], 1, _recvType, ngb, 0, _cartesian_comm, &status);