У меня есть свой собственный класс class2
в файле .h
, и я использую его для создания структуры, например, кода ниже. (Весь код проверяется и полное)мой собственный тип класса плохо работает с MPI_scatterv и Gatherv
#include <mpi.h>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <sys/time.h>
#include <string.h>
#include <numeric>
#include <iterator>
#include "class2.h"
#define MPI_CLASS2 MPI_FLOAT
using namespace std;
struct Pcle
{
Class2 Pot;
Class2 Vy;
float ss;
Pcle(){}; //default empty constructor
Pcle(float M, int Px, int Py) // constructor
:Pot(Px, Py)
, Vy(0.f, 0.f)
, ss (M)
{}
};
Я обеспечу файл .h
также, если это необходимо. проблема заключается в том, что логически значения передавались как MPI_Scatterv
, так и MPI_Gatherv
при изменении конца (или, по крайней мере, некоторые из них), и когда я пытаюсь перейти от Class2
к простому int
типам (и, очевидно, полностью изменить идею) код работает нормально , Для того, чтобы иметь представление о том здесь мой main
файл, который дает хорошие результаты с int
вместо Class2
int main(int argc, char *argv[]){
int size, rank, chunk,j=0;
int recvcount, part;
vector<Pcle> in;
vector<Pcle> c;
vector<Pcle> f;
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Comm_size(MPI_COMM_WORLD,&size);
MPI_Datatype MPI_PART, oldtypes[2];
int blockcounts[2];
// MPI_Aint type used to be consistent with syntax of
// MPI_Type_extent routine
MPI_Aint offsets[2], extent;
MPI_Status stat;
offsets[0] = 0;
oldtypes[0] = MPI_CLASS2;
blockcounts[0] = 2;
// Setup description of the 1 MPI_FLOAT field, Mass
// Need to first figure offset by getting size of MPI_Vector2
MPI_Type_extent(MPI_CLASS2, &extent);
offsets[1] = 2*extent;
oldtypes[1] = MPI_FLOAT;
blockcounts[1] = 1;
// Define structured type and commit it
MPI_Type_struct(2, blockcounts, offsets, oldtypes, &MPI_PART);
MPI_Type_commit(&MPI_PART);
if (rank ==0){ //initalizing stuff in rank ==0
part = 64;
chunk = floorf(part/size);
for (int i=0; i< part; i++){
in.push_back(Pcle(i,2*i,2.5*i));
f.push_back(Pcle());
}
}
//broadcasting needed variables
MPI_Bcast(&chunk, 1, MPI_INT, 0, MPI_COMM_WORLD);
MPI_Bcast(&part,1,MPI_INT,0,MPI_COMM_WORLD);
int sendcount[size];
//creating the arguments for scatterv
for(size_t ct = 0; ct<size; ct++){
if (ct < part%size)
sendcount[ct] = chunk+1;
else
sendcount[ct] = chunk;
}
int displs[size];
displs[0]=0;
for (j =1; j< size; j++)
displs[j] = displs[j-1] +sendcount[j];
recvcount = sendcount[rank];
c.reserve(recvcount);
MPI_Scatterv(in.data(), sendcount, displs, MPI_PART, c.data(), recvcount, MPI_PART, 0, MPI_COMM_WORLD);
for(int iteration =0; iteration <10; ++iteration){
//two functions which changes some of the data in Pot but leaves ss the same and can be left out
MPI_Gatherv(c.data(), sendcount[rank], MPI_PART, f.data(), sendcount, displs, MPI_PART, 0, MPI_COMM_WORLD);
}
if(rank ==0)
for (int k=0; k<64; k++)
cout<<f[k].ss<<" ";
MPI_Finalize();
return 0;
}
Выходом этого кода
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Program ended with exit code: 0
последние несколько значений остается нулевой, что неправильно. Я полностью исключил свой класс и попробовал работать с типом int
вместо class2
в структуре и другим измененным кодом. результаты были правильными
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 Program ended with exit code: 0
Насколько я знаю, я полагаю, что я не правильно определяю класс для MPI. Я пишу #define MPI_CLASS2 MPI_FLOAT
с инструкциями препроцессора, возможно, с этим что-то не так.
вот заголовочный файл. при этом код должен быть скомпилирован и реплицируется результат.
#pragma once
#include <math.h>
#include <assert.h>
struct Class2
{
union
{
float Element[2];
struct { float X, Y; };
struct { float U, V; };
};
Class2() {}
Class2(float p_fValue)
: X(p_fValue), Y(p_fValue) {}
Class2(float p_x, float p_y)
: X(p_x), Y(p_y) {}
Class2(const Class2 &p_vector)
: X(p_vector.X), Y(p_vector.Y) {}
float operator[](int p_nIndex) const { return Element[p_nIndex]; }
float& operator[](int p_nIndex) { return Element[p_nIndex]; }
inline void Set(float p_x, float p_y) {
X = p_x; Y = p_y;
}
inline bool Equals(const Class2 &p_vector, const float p_epsilon = 1e-5f) const
{
if (fabs(X - p_vector.X) > p_epsilon) return false;
if (fabs(Y - p_vector.Y) > p_epsilon) return false;
return true;
}
Class2& operator=(const Class2 &p_vector)
{
X = p_vector.X;
Y = p_vector.Y;
return *this;
}
inline bool operator==(const Class2 &p_vector) const {
return Equals(p_vector);
}
inline bool operator!=(const Class2& p_vector) const {
return !(*this == p_vector);
}
inline Class2 operator*(float p_fValue) const {
return Class2(p_fValue * X, p_fValue * Y);
}
inline Class2 operator/(float p_fValue) const
{
assert(p_fValue != 0.f);
return Class2(*this * (1.0f/p_fValue));
}
inline Class2 operator*(const Class2 &p_vector) const {
return Class2(p_vector.X * X, p_vector.Y * Y);
}
inline Class2 operator+(const Class2 &p_vector) const {
return Class2(X + p_vector.X, Y + p_vector.Y);
}
inline Class2 operator-(const Class2 &p_vector) const {
return Class2(X - p_vector.X, Y - p_vector.Y);
}
inline Class2 operator-(void) const {
return Class2(-X, -Y);
}
inline Class2& operator*=(float p_fValue) {
return *this = *this * p_fValue;
}
inline Class2& operator*=(const Class2 &p_vector) {
return *this = *this * p_vector;
}
inline Class2& operator/=(float p_fValue) {
return *this = *this/p_fValue;
}
inline Class2& operator+=(const Class2 &p_vector) {
return *this = *this + p_vector;
}
inline Class2& operator-=(const Class2 &p_vector) {
return *this = *this - p_vector;
}
inline float MaxComponent() const {
return std::max(X, Y);
}
inline float MinComponent() const {
return std::min(X, Y);
}
inline float MaxAbsComponent() const {
return std::max(fabs(X), fabs(Y));
}
inline float MinAbsComponent() const
{
return std::min(fabs(X), fabs(Y));
}
static Class2 Max(const Class2 &p_vector1, const Class2 &p_vector2)
{
return Class2(std::max(p_vector1.X, p_vector2.X),
std::max(p_vector1.Y, p_vector2.Y));
}
static Class2 Min(const Class2 &p_vector1, const Class2 &p_vector2)
{
return Class2(std::min(p_vector1.X, p_vector2.X),
std::min(p_vector1.Y, p_vector2.Y));
}
inline float Length(void) const {
return sqrt(X * X + Y * Y);
}
inline float LengthSquared(void) const {
return X * X + Y * Y;
}
inline void Normalize(void) {
*this = Class2::Normalize(*this);
}
inline float Dot(const Class2 &p_vector) const {
return Class2::Dot(*this, p_vector);
}
inline float AbsDot(const Class2 &p_vector) const {
return Class2::AbsDot(*this, p_vector);
}
static float Dot(const Class2 &p_vector1, const Class2 &p_vector2) {
return p_vector1.X * p_vector2.X + p_vector1.Y * p_vector2.Y;
}
static float AbsDot(const Class2 &p_vector1, const Class2 &p_vector2) {
return fabs(p_vector1.X * p_vector2.X +
p_vector1.Y * p_vector2.Y);
}
static Class2 Normalize(const Class2 &p_vector) {
return p_vector/sqrt(p_vector.Length());
}
static float DistanceSquared(const Class2 &p_point1, const Class2 &p_point2) {
return (p_point2 - p_point1).LengthSquared();
}
static float Distance(const Class2 &p_point1, const Class2 &p_point2) {
return (p_point2 - p_point1).Length();
}
};
inline Class2 operator*(float p_fValue, const Class2 &p_vector) {
return Class2(p_fValue * p_vector.X, p_fValue * p_vector.Y);
}
Не могли бы вы предоставить полный минимальный код, который можно скомпилировать и выполнить? –
@HristoIliev Я обновляю вопрос с кодом, необходимым для повторения моего первого результата. – user7331538
Я был бы признателен за некоторые отзывы, так как я давно застрял на этом – user7331538