library(Rmpi)
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <mpi.h>
// Define a structure to hold data points with features and labels
typedef struct {
double features[2];
int label;
} DataPoint;
double euclidean_distance(double *x1, double *x2, int num_features) {
// the Euclidean distance between two points is the square root of the sum of the squared
// differences between the corresponding values
double distance = 0.0;
for (int i = 0; i < num_features; i++) {
distance
+= pow(x1
[i
] - x2
[i
], 2); }
}
void find_k_nearest_neighbours(DataPoint *train_data, int train_size, double *test_point, int num_features, int k, double *distances, int *labels) {
for (int i = 0; i < train_data; i++) {
distances[i] = euclidean_distance(train_data[i].features, test_point, num_features);
labels[i] = train_data[i].label;
}
}
int main(int argc, char *argv[]) {
// Initialize MPI
MPI_Init(&argc, &argv);
int rank, size;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
// Define the training data
int num_features = 2;
int train_size = 12;
DataPoint train_data[12] = {
{{1.0, 1.0}, 0},
{{1.0, 2.0}, 0},
{{2.0, 1.0}, 0},
{{2.0, 2.0}, 0},
{{5.0, 5.0}, 1},
{{5.0, 6.0}, 1},
{{6.0, 5.0}, 1},
{{6.0, 6.0}, 1},
{{10.0, 10.0}, 2},
{{10.0, 11.0}, 2},
{{11.0, 10.0}, 2},
{{11.0, 11.0}, 2}
};
// Define the test data
double test_point[2] = {3.0, 3.0};
int k = 3;
// Allocate memory for arrays to hold distances and labels
int local_size = train_size / size;
int remainder = train_size % size;
int *sendcounts
= (int *)malloc(size
* sizeof(int)); int *displs
= (int *)malloc(size
* sizeof(int)); for (int i = 0; i < size; i++) {
sendcounts[i] = (i < remainder) ? local_size + 1 : local_size;
displs[i] = (i == 0) ? 0 : displs[i - 1] + sendcounts[i - 1];
}
double *local_train_data
= (DataPoint
*)malloc(sendcounts
[rank
] * sizeof(DataPoint
)); MPI_Scatterv(train_data, sendcounts, displs, MPI_DOUBLE, local_train_data, sendcounts[rank], MPI_DOUBLE, 0, MPI_COMM_WORLD);
double *local_distances
= (double *)malloc(sendcounts
[rank
] * sizeof(double)); int *local_labels
= (int *)malloc(sendcounts
[rank
] * sizeof(int));
find_k_nearest_neighbours(local_train_data, sendcounts[rank], test_point, num_features, k, local_distances, local_labels);
double *distances = NULL;
int *labels = NULL;
if (rank == 0) {
distances
= (double *)malloc(train_size
* sizeof(double)); labels
= (int *)malloc(train_size
* sizeof(int)); }
MPI_Gatherv(local_distances, sendcounts[rank], MPI_DOUBLE, distances, sendcounts, displs, MPI_DOUBLE, 0, MPI_COMM_WORLD);
MPI_Gatherv(local_labels, sendcounts[rank], MPI_INT, labels, sendcounts, displs, MPI_INT, 0, MPI_COMM_WORLD);
if (rank == 0) {
for (int i = 0; i < train_size - 1; i++) {
for (int j = i + 1; j < train_size; j++) {
if (distances[i] > distances[j]) {
double temp_distance = distances[i];
distances[i] = distances[j];
distances[j] = temp_distance;
int temp_label = labels[i];
labels[i] = labels[j];
labels[j] = temp_label;
}
}
}
// find the most common label among the k nearest neighbours
int *label_count
= (int *)calloc(train_size
, sizeof(int)); for (int i = 0; i < k; i++) {
label_count[labels[i]]++;
}
// Find the label with the maximum count
int max_count = 0;
int predicted_label = -1;
for (int i = 0; i < train_size; i++) {
if (label_count[i] > max_count) {
max_count = label_count[i];
predicted_label = i;
}
}
printf("Predicted label: %d\n", predicted_label
); }
// Finalize MPI
MPI_Finalize();
return 0;
}
bGlicmFyeShSbXBpKQoKI2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPG1hdGguaD4KI2luY2x1ZGUgPG1waS5oPgoKCi8vIERlZmluZSBhIHN0cnVjdHVyZSB0byBob2xkIGRhdGEgcG9pbnRzIHdpdGggZmVhdHVyZXMgYW5kIGxhYmVscwp0eXBlZGVmIHN0cnVjdCB7CiAgICBkb3VibGUgZmVhdHVyZXNbMl07CiAgICBpbnQgbGFiZWw7Cn0gRGF0YVBvaW50OwoKZG91YmxlIGV1Y2xpZGVhbl9kaXN0YW5jZShkb3VibGUgKngxLCBkb3VibGUgKngyLCBpbnQgbnVtX2ZlYXR1cmVzKSB7CiAgICAvLyB0aGUgRXVjbGlkZWFuIGRpc3RhbmNlIGJldHdlZW4gdHdvIHBvaW50cyBpcyB0aGUgc3F1YXJlIHJvb3Qgb2YgdGhlIHN1bSBvZiB0aGUgc3F1YXJlZCAKICAgIC8vIGRpZmZlcmVuY2VzIGJldHdlZW4gdGhlIGNvcnJlc3BvbmRpbmcgdmFsdWVzCiAgICBkb3VibGUgZGlzdGFuY2UgPSAwLjA7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IG51bV9mZWF0dXJlczsgaSsrKSB7CiAgICAgICAgZGlzdGFuY2UgKz0gcG93KHgxW2ldIC0geDJbaV0sIDIpOwogICAgfQoKICAgIHJldHVybiBzcXJ0KGRpc3RhbmNlKTsKfQoKdm9pZCBmaW5kX2tfbmVhcmVzdF9uZWlnaGJvdXJzKERhdGFQb2ludCAqdHJhaW5fZGF0YSwgaW50IHRyYWluX3NpemUsIGRvdWJsZSAqdGVzdF9wb2ludCwgaW50IG51bV9mZWF0dXJlcywgaW50IGssIGRvdWJsZSAqZGlzdGFuY2VzLCBpbnQgKmxhYmVscykgewogICAgZm9yIChpbnQgaSA9IDA7IGkgPCB0cmFpbl9kYXRhOyBpKyspIHsKICAgICAgICBkaXN0YW5jZXNbaV0gPSBldWNsaWRlYW5fZGlzdGFuY2UodHJhaW5fZGF0YVtpXS5mZWF0dXJlcywgdGVzdF9wb2ludCwgbnVtX2ZlYXR1cmVzKTsKICAgICAgICBsYWJlbHNbaV0gPSB0cmFpbl9kYXRhW2ldLmxhYmVsOwogICAgfQp9CgppbnQgbWFpbihpbnQgYXJnYywgY2hhciAqYXJndltdKSB7CiAgICAvLyBJbml0aWFsaXplIE1QSQogICAgTVBJX0luaXQoJmFyZ2MsICZhcmd2KTsKCiAgICBpbnQgcmFuaywgc2l6ZTsKICAgIE1QSV9Db21tX3JhbmsoTVBJX0NPTU1fV09STEQsICZyYW5rKTsKICAgIE1QSV9Db21tX3NpemUoTVBJX0NPTU1fV09STEQsICZzaXplKTsKCiAgICAvLyBEZWZpbmUgdGhlIHRyYWluaW5nIGRhdGEKICAgIGludCBudW1fZmVhdHVyZXMgPSAyOwogICAgaW50IHRyYWluX3NpemUgPSAxMjsKCiAgICBEYXRhUG9pbnQgdHJhaW5fZGF0YVsxMl0gPSB7CiAgICAgICAge3sxLjAsIDEuMH0sIDB9LAogICAgICAgIHt7MS4wLCAyLjB9LCAwfSwKICAgICAgICB7ezIuMCwgMS4wfSwgMH0sCiAgICAgICAge3syLjAsIDIuMH0sIDB9LAogICAgICAgIHt7NS4wLCA1LjB9LCAxfSwKICAgICAgICB7ezUuMCwgNi4wfSwgMX0sCiAgICAgICAge3s2LjAsIDUuMH0sIDF9LAogICAgICAgIHt7Ni4wLCA2LjB9LCAxfSwKICAgICAgICB7ezEwLjAsIDEwLjB9LCAyfSwKICAgICAgICB7ezEwLjAsIDExLjB9LCAyfSwKICAgICAgICB7ezExLjAsIDEwLjB9LCAyfSwKICAgICAgICB7ezExLjAsIDExLjB9LCAyfQogICAgfTsKCiAgICAvLyBEZWZpbmUgdGhlIHRlc3QgZGF0YQogICAgZG91YmxlIHRlc3RfcG9pbnRbMl0gPSB7My4wLCAzLjB9OwogICAgaW50IGsgPSAzOwoKICAgIC8vIEFsbG9jYXRlIG1lbW9yeSBmb3IgYXJyYXlzIHRvIGhvbGQgZGlzdGFuY2VzIGFuZCBsYWJlbHMKICAgIGludCBsb2NhbF9zaXplID0gdHJhaW5fc2l6ZSAvIHNpemU7CiAgICBpbnQgcmVtYWluZGVyID0gdHJhaW5fc2l6ZSAlIHNpemU7CgogICAgaW50ICpzZW5kY291bnRzID0gKGludCAqKW1hbGxvYyhzaXplICogc2l6ZW9mKGludCkpOwogICAgaW50ICpkaXNwbHMgPSAoaW50ICopbWFsbG9jKHNpemUgKiBzaXplb2YoaW50KSk7CiAgICBmb3IgKGludCBpID0gMDsgaSA8IHNpemU7IGkrKykgewogICAgICAgIHNlbmRjb3VudHNbaV0gPSAoaSA8IHJlbWFpbmRlcikgPyBsb2NhbF9zaXplICsgMSA6IGxvY2FsX3NpemU7CiAgICAgICAgZGlzcGxzW2ldID0gKGkgPT0gMCkgPyAwIDogZGlzcGxzW2kgLSAxXSArIHNlbmRjb3VudHNbaSAtIDFdOwogICAgfQoKICAgIGRvdWJsZSAqbG9jYWxfdHJhaW5fZGF0YSA9IChEYXRhUG9pbnQgKiltYWxsb2Moc2VuZGNvdW50c1tyYW5rXSAqIHNpemVvZihEYXRhUG9pbnQpKTsKICAgIE1QSV9TY2F0dGVydih0cmFpbl9kYXRhLCBzZW5kY291bnRzLCBkaXNwbHMsIE1QSV9ET1VCTEUsIGxvY2FsX3RyYWluX2RhdGEsIHNlbmRjb3VudHNbcmFua10sIE1QSV9ET1VCTEUsIDAsIE1QSV9DT01NX1dPUkxEKTsKCiAgICBkb3VibGUgKmxvY2FsX2Rpc3RhbmNlcyA9IChkb3VibGUgKiltYWxsb2Moc2VuZGNvdW50c1tyYW5rXSAqIHNpemVvZihkb3VibGUpKTsKICAgIGludCAqbG9jYWxfbGFiZWxzID0gKGludCAqKW1hbGxvYyhzZW5kY291bnRzW3JhbmtdICogc2l6ZW9mKGludCkpOwoKICAgIGZpbmRfa19uZWFyZXN0X25laWdoYm91cnMobG9jYWxfdHJhaW5fZGF0YSwgc2VuZGNvdW50c1tyYW5rXSwgdGVzdF9wb2ludCwgbnVtX2ZlYXR1cmVzLCBrLCBsb2NhbF9kaXN0YW5jZXMsIGxvY2FsX2xhYmVscyk7CgogICAgZG91YmxlICpkaXN0YW5jZXMgPSBOVUxMOwogICAgaW50ICpsYWJlbHMgPSBOVUxMOwoKICAgIGlmIChyYW5rID09IDApIHsKICAgICAgICBkaXN0YW5jZXMgPSAoZG91YmxlICopbWFsbG9jKHRyYWluX3NpemUgKiBzaXplb2YoZG91YmxlKSk7CiAgICAgICAgbGFiZWxzID0gKGludCAqKW1hbGxvYyh0cmFpbl9zaXplICogc2l6ZW9mKGludCkpOwogICAgfQoKICAgIE1QSV9HYXRoZXJ2KGxvY2FsX2Rpc3RhbmNlcywgc2VuZGNvdW50c1tyYW5rXSwgTVBJX0RPVUJMRSwgZGlzdGFuY2VzLCBzZW5kY291bnRzLCBkaXNwbHMsIE1QSV9ET1VCTEUsIDAsIE1QSV9DT01NX1dPUkxEKTsKICAgIE1QSV9HYXRoZXJ2KGxvY2FsX2xhYmVscywgc2VuZGNvdW50c1tyYW5rXSwgTVBJX0lOVCwgbGFiZWxzLCBzZW5kY291bnRzLCBkaXNwbHMsIE1QSV9JTlQsIDAsIE1QSV9DT01NX1dPUkxEKTsKCiAgICBpZiAocmFuayA9PSAwKSB7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCB0cmFpbl9zaXplIC0gMTsgaSsrKSB7CiAgICAgICAgICAgIGZvciAoaW50IGogPSBpICsgMTsgaiA8IHRyYWluX3NpemU7IGorKykgewogICAgICAgICAgICAgICAgaWYgKGRpc3RhbmNlc1tpXSA+IGRpc3RhbmNlc1tqXSkgewogICAgICAgICAgICAgICAgICAgIGRvdWJsZSB0ZW1wX2Rpc3RhbmNlID0gZGlzdGFuY2VzW2ldOwogICAgICAgICAgICAgICAgICAgIGRpc3RhbmNlc1tpXSA9IGRpc3RhbmNlc1tqXTsKICAgICAgICAgICAgICAgICAgICBkaXN0YW5jZXNbal0gPSB0ZW1wX2Rpc3RhbmNlOwoKICAgICAgICAgICAgICAgICAgICBpbnQgdGVtcF9sYWJlbCA9IGxhYmVsc1tpXTsKICAgICAgICAgICAgICAgICAgICBsYWJlbHNbaV0gPSBsYWJlbHNbal07CiAgICAgICAgICAgICAgICAgICAgbGFiZWxzW2pdID0gdGVtcF9sYWJlbDsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgLy8gZmluZCB0aGUgbW9zdCBjb21tb24gbGFiZWwgYW1vbmcgdGhlIGsgbmVhcmVzdCBuZWlnaGJvdXJzCiAgICAgICAgaW50ICpsYWJlbF9jb3VudCA9IChpbnQgKiljYWxsb2ModHJhaW5fc2l6ZSwgc2l6ZW9mKGludCkpOwogICAgICAgIGZvciAoaW50IGkgPSAwOyBpIDwgazsgaSsrKSB7CiAgICAgICAgICAgIGxhYmVsX2NvdW50W2xhYmVsc1tpXV0rKzsKICAgICAgICB9CgogICAgICAgIC8vIEZpbmQgdGhlIGxhYmVsIHdpdGggdGhlIG1heGltdW0gY291bnQKICAgICAgICBpbnQgbWF4X2NvdW50ID0gMDsKICAgICAgICBpbnQgcHJlZGljdGVkX2xhYmVsID0gLTE7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPCB0cmFpbl9zaXplOyBpKyspIHsKICAgICAgICAgICAgaWYgKGxhYmVsX2NvdW50W2ldID4gbWF4X2NvdW50KSB7CiAgICAgICAgICAgICAgICBtYXhfY291bnQgPSBsYWJlbF9jb3VudFtpXTsKICAgICAgICAgICAgICAgIHByZWRpY3RlZF9sYWJlbCA9IGk7CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgICAgIGZyZWUoZGlzdGFuY2VzKTsKICAgICAgICBmcmVlKGxhYmVscyk7CiAgICAgICAgZnJlZShsYWJlbF9jb3VudCk7CgogICAgICAgIHByaW50ZigiUHJlZGljdGVkIGxhYmVsOiAlZFxuIiwgcHJlZGljdGVkX2xhYmVsKTsKICAgIH0KCiAgICBmcmVlKGxvY2FsX3RyYWluX2RhdGEpOwogICAgZnJlZShsb2NhbF9kaXN0YW5jZXMpOwogICAgZnJlZShsb2NhbF9sYWJlbHMpOwogICAgZnJlZShzZW5kY291bnRzKTsKICAgIGZyZWUoZGlzcGxzKTsKCiAgICAvLyBGaW5hbGl6ZSBNUEkKICAgIE1QSV9GaW5hbGl6ZSgpOwoKICAgIHJldHVybiAwOwp9