我的 MPI 程序不能与 C++ Vector Class 一起工作

问题描述 投票:0回答:0

我正在尝试运行 p 到 p MPI 程序来进行集群。该程序的一个进程应该使用 C++ Vector 类,它包含预制的 Point 类。当我在 Visual Studio 中运行程序时,我得到了 Points in vector 的输出。但是当我运行 mpiexe 时,跳过了使用 vector 的代码部分。我应该怎么做才能教 MPI 使用向量类?

我的代码:

#include <ctime>
#include <fstream>
#include <iostream>
#include <sstream>
#include <vector>
#include <stdio.h>
#include <chrono>
#include <mpi.h>
#include <stdlib.h>
#include <float.h>


using namespace std;
using namespace std::chrono;

// allocate in memory 2-dimensional array
float** alloc_2d_float(int rows, int cols) {
    float* data = (float*)malloc(rows * cols * sizeof(float));
    float** array = (float**)malloc(rows * sizeof(float*));
    for (int i = 0; i < rows; i++)
        array[i] = &(data[cols * i]);

    return array;
}

struct Point {
public:
    double x, y;     // coordinates
    int cluster;     // no default cluster
    double minDist;  // default infinite distance to nearest cluster

    Point() : x(0.0), y(0.0), cluster(-1), minDist(DBL_MAX) {}
    Point(double x, double y) : x(x), y(y), cluster(-1), minDist(DBL_MAX) {}

    // Computes the (square) euclidean distance between this point and another
    double distance(Point p) {
        return (p.x - x) * (p.x - x) + (p.y - y) * (p.y - y);
    }
    friend std::ostream& operator<< (std::ostream& out, const Point& point);
};

std::ostream& operator<< (std::ostream& out, const Point& point)
{

    out << "Point(" << point.x << ", " << point.y << ", " << point.cluster << ')' << "\n";

    return out;
}

// reads data from 2-d array into vector of points
vector<Point> read_data(float** XY, int n) {
    vector<Point> points;
    double x, y;
    for (int i = 0; i < n; i++) {
        x = XY[i][0];
        y = XY[i][1];
        points.push_back(Point(x, y));
    }
    return points;
}

// calculate Calinsky-Harabatzs index
float calc_CH(int n, int k, float** out) {
    float x_m = 0; // mean value of x
    float y_m = 0; // mean value of y
    float Wk = 0;  // within group dispersion
    float T = 0;   // data scatter
    float CH = 0;  // Calinsky-Harabatsz index

    // calculate means and Wk
    for (int i = 0; i < n; i++) {
        x_m += out[i][0];
        y_m += out[i][1];
        Wk += ((out[i][0] - out[i][3]) * (out[i][0] - out[i][3]) + (out[i][1] - out[i][4]) * (out[i][1] - out[i][4]));
    }
    x_m = x_m / n;
    y_m = y_m / n;

    // calculate T
    for (int i = 0; i < n; i++) {
        T += ((out[i][0] - x_m) * (out[i][0] - x_m) + (out[i][1] - y_m) * (out[i][1] - y_m));
    }

    // calculate CH
    CH = (T - Wk) * (k - 1) / (Wk * (n - k));

    return CH;
}

void kMeansClustering(vector<Point>* points, float** out, int epochs, int k, float** centers) {
    int n = points->size();

    // Randomly initialise centroids
    // The index of the centroid within the centroids vector
    // represents the cluster label.
    vector<Point> centroids;
    srand(time(0));
    //for (int i = 0; i < k; ++i) {
    //    centroids.push_back(points->at(rand() % n));
    //}

    //for (int i = 0; i < epochs; ++i) {
    //    // For each centroid, compute distance from centroid to each point
    //    // and update point's cluster if necessary
    //    for (vector<Point>::iterator c = begin(centroids); c != end(centroids);
    //        ++c) {
    //        int clusterId = c - begin(centroids);

    //        for (vector<Point>::iterator it = points->begin();
    //            it != points->end(); ++it) {
    //            Point p = *it;
    //            double dist = c->distance(p);
    //            if (dist < p.minDist) {
    //                p.minDist = dist;
    //                p.cluster = clusterId;
    //            }
    //            *it = p;
    //        }
    //    }

    //    // Create vectors to keep track of data needed to compute means
    //    vector<int> nPoints;
    //    vector<double> sumX, sumY;
    //    for (int j = 0; j < k; ++j) {
    //        nPoints.push_back(0);
    //        sumX.push_back(0.0);
    //        sumY.push_back(0.0);
    //    }

    //    // Iterate over points to append data to centroids
    //    for (vector<Point>::iterator it = points->begin(); it != points->end();
    //        ++it) {
    //        int clusterId = it->cluster;
    //        nPoints[clusterId] += 1;
    //        sumX[clusterId] += it->x;
    //        sumY[clusterId] += it->y;

    //        it->minDist = DBL_MAX;  // reset distance
    //    }
    //    // Compute the new centroids
    //    for (vector<Point>::iterator c = begin(centroids); c != end(centroids);
    //        ++c) {
    //        int clusterId = c - begin(centroids);
    //        c->x = sumX[clusterId] / nPoints[clusterId];
    //        c->y = sumY[clusterId] / nPoints[clusterId];
    //    }
    //}

    //// Write to csv computed points
    //ofstream myfile1;
    //myfile1.open("./output.csv");
    //myfile1 << "x,y,c" << endl;
    //for (vector<Point>::iterator it = points->begin(); it != points->end();
    //    ++it) {
    //    myfile1 << it->x << "," << it->y << "," << it->cluster << endl;
    //}
    //myfile1.close();

    //// Write to csv final centroids
    //ofstream myfile2;
    //myfile2.open("./centroids.csv");
    //myfile2 << "x,y,c" << endl;
    //int count = 0;
    //for (vector<Point>::iterator c = begin(centroids); c != end(centroids);
    //    ++c) {
    //    int clusterId = c - begin(centroids);
    //    // fill array with centroids 
    //    centers[count][0] = c->x;
    //    centers[count][1] = c->y;
    //    centers[count][2] = clusterId;
    //    myfile2 << centers[count][0] << "," << centers[count][1] << "," << centers[count][2] << "\n";
    //    ++count;
    //}
    //myfile2.close();
    //count = 0;

    //// Save points, centroid index and coordinates in one array
    //// fill the array
    //for (vector<Point>::iterator it = points->begin(); it != points->end();
    //    ++it) {
    //    for (vector<Point>::iterator c = begin(centroids); c != end(centroids);
    //        ++c) {
    //        int clusterId = c - begin(centroids);
    //        if (clusterId == it->cluster) {
    //            out[count][0] = it->x;
    //            out[count][1] = it->y;
    //            out[count][2] = it->cluster;
    //            out[count][3] = c->x;
    //            out[count][4] = c->y;
    //        }
    //    }
    //    count++;
    //}
}

// Calculate number of lines in .csv file ( number of elements for axis in 2-d array)
int calc_n(std::string file) {
    int n = 0;
    std::string line;
    std::ifstream myfile(file);

    while (std::getline(myfile, line)) {
        ++n;
    }
    return n;
}

// Fill the 2-d floats array of points, passed by pointer from the .csv file
void fill_XY(std::string file, float** XY) {
    std::string line;
    std::ifstream myfile(file);
    int i = 0;

    while (std::getline(myfile, line)) {
        std::stringstream lineStream(line);
        std::string bit;
        float x, y;
        std::getline(lineStream, bit, ',');
        x = std::stof(bit);
        std::getline(lineStream, bit, '\n');
        y = std::stof(bit);
        XY[i][0] = x;
        XY[i][1] = y;
        ++i;
    }
}

int main() {

    double time1, time2, duration, global;



    MPI_Init(NULL, NULL);
    // Get starting timepoint
    time1 = MPI_Wtime();
    int world_size;
    MPI_Comm_size(MPI_COMM_WORLD, &world_size);
    int world_rank;
    MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);

    std::string file = "./XY2.csv";  // input file
    int n = calc_n(file);           // number of points in file
    int k = 5;                      // number of clusters
    float** XY;                     // input data array
    float** centers;                // output array of centroids

    if (world_rank == 0) {

        // allocate data array 
        XY = alloc_2d_float(n, 2);

        // fill the array from file
        fill_XY(file, XY);

        //vector<Point> points1 = read_data(XY, n);

        //vector<Point> centroids;
        //srand(time(0));
        //for (int i = 0; i < k; ++i) {
        //    //centroids.push_back((&points)->at(rand() % 2));
        //    centroids.push_back(points1[i]);
        //}
        vector<Point> points = read_data(XY, n);




        // Send the data to the first process
        MPI_Send(&(XY[0][0]), 2 * n, MPI_FLOAT, 1, 0, MPI_COMM_WORLD);
        // allocate an array of centroids
        centers = alloc_2d_float(k, 3);

        // receive centroids coordinates
        MPI_Recv(&(centers[0][0]), k * 3, MPI_FLOAT, 1, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);

        // output centroids
        cout << "\n Centroids: \n\n";
        for (int i = 0; i < k; i++) {
            cout << centers[i][0] << " " << centers[i][1] << " " << centers[i][2] << "\n";
        }

        // receive the CH-value    
        float ch = 0;
        MPI_Recv(&ch, 1, MPI_FLOAT, 1, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);

        // output CH-value
        cout << "\n" << "CH-value: " << ch << "\n\n";

        vector<Point>::iterator p;
        p = points.begin();
        while (p != points.end())
        {
            cout << *p << "Something ";
            p++;
        }
    }

    if (world_rank > 0) {

        // allocate data array
        XY = alloc_2d_float(n, 2);

        // Receive at most MAX_NUMBERS from process zero
        MPI_Recv(&(XY[0][0]), 2 * n, MPI_FLOAT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);

        // fill the points vector
        vector<Point> points = read_data(XY, n);

        // create an output array of kMeans
        float** out;
        out = alloc_2d_float(n, k);

        // allocate an output array of centroids
        centers = alloc_2d_float(k, 3);

        // THAT PART OF CODE DIDN'T DONE
        vector<Point>::iterator p;
        p = points.begin();
        while (p != points.end())
        {
            cout << *p << "Something ";
            p++;
        }

        // Run k-means with 100 iterations and for 5 clusters
        cout << "\n" << "Clustering " <<  "\n\n";
        //KmeansClustering(&points, out, 100, k, centers);
        
        // Calculate clustering efficiency by CH-index
        //float ch = calc_CH(n, k, out);
        float ch = calc_CH(n, k, out);

        // Send the centroids array to process zero
        MPI_Send(&(centers[0][0]), k * 3, MPI_FLOAT, 0, 0, MPI_COMM_WORLD);

        // Send the CH-value to the process zero
        MPI_Send(&ch, 1, MPI_FLOAT, 0, 0, MPI_COMM_WORLD);
    }

    // Get ending timepoint
    time2 = MPI_Wtime();

    // Calculate duration
    duration = time2 - time1;

    // Calculate global runtime
    MPI_Reduce(&duration, &global, 1, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD);
    if (world_rank == 0) {
        printf("Global runtime is %f\n", global);
    }

    MPI_Finalize();

    return 0;
}

现在我想在矢量的 cmd 元素中显示。我想在 rank > 0 的过程中创建向量,在控制台中显示它。我没有兴趣将这个课程发送到另一个过程。

c++ mpi stdvector
© www.soinside.com 2019 - 2024. All rights reserved.