Apostolos Fanakis
6 years ago
commit
f3ef16d3eb
169 changed files with 131028 additions and 0 deletions
@ -0,0 +1,21 @@ |
|||||
|
TARGET=KnnMPIBlockingSpaceOptimized |
||||
|
CC=mpicc |
||||
|
CFLAGS=-Wall -O3 -std=gnu99 -I. |
||||
|
OBJ=knnMPIBlocking.o knnMPIBlockingDeclarations.o |
||||
|
DEPS=knnMPIBlockingDeclarations.h |
||||
|
|
||||
|
.PHONY: default all clean |
||||
|
|
||||
|
default: $(TARGET) |
||||
|
all: default |
||||
|
|
||||
|
%.o: %.c $(DEPS) |
||||
|
$(CC) -c -o $@ $< $(CFLAGS) |
||||
|
|
||||
|
.PRECIOUS: $(TARGET) $(OBJ) |
||||
|
|
||||
|
$(TARGET): $(OBJ) |
||||
|
$(CC) -o $@ $^ $(CFLAGS) |
||||
|
|
||||
|
clean: |
||||
|
$(RM) *.o *~ |
@ -0,0 +1,151 @@ |
|||||
|
#include <stdio.h> |
||||
|
#include <sys/time.h> |
||||
|
|
||||
|
#include "knnMPIBlockingDeclarations.h" |
||||
|
#include "mpi.h" |
||||
|
|
||||
|
/* Structs */ |
||||
|
struct timeval startwtime, endwtime |
||||
|
, commStartWTime, commEndWTime |
||||
|
, calcStartWTime, calcEndWTime; |
||||
|
|
||||
|
/* Global variables */ |
||||
|
int numberOfPoints = 0, numberOfDimensions = 0, numberOfNeighbors = 0; |
||||
|
char *pointsFilename = NULL, *testFilename = NULL; |
||||
|
double seq_time = 0; |
||||
|
|
||||
|
/* Main */ |
||||
|
int main(int argc, char **argv){ |
||||
|
int numberOfTasks = 0, taskId = 0, chunksize = 0, myOffset = 0, destination = 0, source = 0; |
||||
|
double **myPoints, **inBuffer, **outBuffer, commTimeSum = 0, calcTimeSum = 0; |
||||
|
neighbor **sortedNeighborsArray; |
||||
|
MPI_Status status; |
||||
|
|
||||
|
getArguments(argc, argv); |
||||
|
|
||||
|
//Initializes mpi and necessary variables
|
||||
|
MPI_Init(&argc, &argv); |
||||
|
MPI_Comm_size(MPI_COMM_WORLD, &numberOfTasks); |
||||
|
if (numberOfPoints % numberOfTasks != 0){ |
||||
|
printf("Quitting. Number of points must be divisible by number of MPI tasks.\n"); |
||||
|
abExit(0); |
||||
|
} |
||||
|
MPI_Comm_rank(MPI_COMM_WORLD, &taskId); |
||||
|
|
||||
|
chunksize = numberOfPoints / numberOfTasks; //number of points each task has
|
||||
|
myOffset = taskId * chunksize; //this task's offset from (complete) point's array start
|
||||
|
destination = taskId + 1; //this task's destination task id for sending messages
|
||||
|
if (destination >= numberOfTasks){ |
||||
|
destination = 0; |
||||
|
} |
||||
|
source= taskId - 1; //this task's source task id for receiving messages
|
||||
|
if (source < 0){ |
||||
|
source = numberOfTasks - 1; |
||||
|
} |
||||
|
|
||||
|
init(&myPoints, &inBuffer, &outBuffer, &sortedNeighborsArray, chunksize |
||||
|
, myOffset * numberOfDimensions); |
||||
|
|
||||
|
MPI_Barrier(MPI_COMM_WORLD); |
||||
|
if (taskId == MASTER){ |
||||
|
gettimeofday(&startwtime, NULL); |
||||
|
} |
||||
|
|
||||
|
gettimeofday(&calcStartWTime, NULL); |
||||
|
|
||||
|
//Calculates distances between task's own points
|
||||
|
calculateDistances(&myPoints, &myPoints, &sortedNeighborsArray, chunksize, myOffset |
||||
|
, taskId * chunksize); |
||||
|
|
||||
|
gettimeofday(&calcEndWTime, NULL); |
||||
|
calcTimeSum += (double)((calcEndWTime.tv_usec - calcStartWTime.tv_usec)/1.0e6 |
||||
|
+ calcEndWTime.tv_sec - calcStartWTime.tv_sec); |
||||
|
|
||||
|
for (int chunk=0; chunk<numberOfTasks-1; ++chunk){ |
||||
|
gettimeofday(&commStartWTime, NULL); |
||||
|
//sends-receives points array blocks
|
||||
|
if (taskId == MASTER){ |
||||
|
//master task sends first to avoid deadlocks
|
||||
|
MPI_Send((chunk == 0) //if this is the first loop
|
||||
|
? &(myPoints[0][0]) //send this task's points
|
||||
|
: &(outBuffer[0][0]) //else send the points received from previous loop
|
||||
|
, chunksize * numberOfDimensions, MPI_DOUBLE, destination, taskId, MPI_COMM_WORLD); |
||||
|
MPI_Recv(&(inBuffer[0][0]), chunksize * numberOfDimensions, MPI_DOUBLE, source, source |
||||
|
, MPI_COMM_WORLD, &status); |
||||
|
} else { |
||||
|
//other tasks receive first
|
||||
|
MPI_Recv(&(inBuffer[0][0]), chunksize * numberOfDimensions, MPI_DOUBLE, source, source |
||||
|
, MPI_COMM_WORLD, &status); |
||||
|
MPI_Send((chunk == 0) //if this is the first loop
|
||||
|
? &(myPoints[0][0]) //send this task's points
|
||||
|
: &(outBuffer[0][0]) //else send the points received from previous loop
|
||||
|
, chunksize * numberOfDimensions, MPI_DOUBLE, destination, taskId, MPI_COMM_WORLD); |
||||
|
} |
||||
|
gettimeofday(&commEndWTime, NULL); |
||||
|
commTimeSum += (double)((commEndWTime.tv_usec - commStartWTime.tv_usec)/1.0e6 |
||||
|
+ commEndWTime.tv_sec - commStartWTime.tv_sec); |
||||
|
|
||||
|
//offset, the task that sent new points block has from (complete) point's array start
|
||||
|
//used for storing the correct neighbor id's in neighbors array
|
||||
|
int offset = source - chunk; |
||||
|
if (offset < 0){ |
||||
|
offset += numberOfTasks; |
||||
|
} |
||||
|
offset *= chunksize; |
||||
|
|
||||
|
gettimeofday(&calcStartWTime, NULL); |
||||
|
|
||||
|
//calculates distances between task's points and new points received
|
||||
|
calculateDistances(&myPoints, &inBuffer, &sortedNeighborsArray, chunksize, myOffset |
||||
|
, offset); |
||||
|
|
||||
|
gettimeofday(&calcEndWTime, NULL); |
||||
|
calcTimeSum += (double)((calcEndWTime.tv_usec - calcStartWTime.tv_usec)/1.0e6 |
||||
|
+ calcEndWTime.tv_sec - calcStartWTime.tv_sec); |
||||
|
|
||||
|
swapPointers(&inBuffer, &outBuffer); |
||||
|
} |
||||
|
|
||||
|
MPI_Barrier(MPI_COMM_WORLD); |
||||
|
if (taskId == MASTER){ |
||||
|
gettimeofday(&endwtime, NULL); |
||||
|
seq_time = (double)((endwtime.tv_usec - startwtime.tv_usec)/1.0e6 |
||||
|
+ endwtime.tv_sec - startwtime.tv_sec); |
||||
|
|
||||
|
printf("Wall clock time = %f\n\n", seq_time); |
||||
|
} |
||||
|
|
||||
|
if (test(&sortedNeighborsArray, chunksize, myOffset, testFilename)){ |
||||
|
printf("Validity check failed for task %d!\n", taskId); |
||||
|
} else { |
||||
|
printf("Validity check success for task %d!\n", taskId); |
||||
|
} |
||||
|
|
||||
|
if (taskId == MASTER){ |
||||
|
printf("Number of points = %d\n", numberOfPoints); |
||||
|
printf("Number of dimensions = %d\n", numberOfDimensions); |
||||
|
printf("Number of neighbors = %d\n", numberOfNeighbors); |
||||
|
printf("Number of tasks = %d\n", numberOfTasks); |
||||
|
} |
||||
|
for(int i=0; i<numberOfTasks; ++i) { |
||||
|
MPI_Barrier(MPI_COMM_WORLD); |
||||
|
if (i == taskId) { |
||||
|
printf("Task %d communications time sum = %f\n", taskId, commTimeSum); |
||||
|
printf("Task %d calculations time sum = %f\n", taskId, calcTimeSum); |
||||
|
|
||||
|
/*
|
||||
|
Uncomment to print the results |
||||
|
*/ |
||||
|
/*for (int x=0; x<chunksize; ++x){
|
||||
|
for (int y=0; y<numberOfNeighbors; ++y){ |
||||
|
printf("%d to %d = %f\n", x + taskId * chunksize |
||||
|
, sortedNeighborsArray[x][y].neighborId, sortedNeighborsArray[x][y].distance); |
||||
|
} |
||||
|
printf("\n"); |
||||
|
}*/ |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
cleanUp(&myPoints, &inBuffer, &outBuffer, &sortedNeighborsArray, chunksize); |
||||
|
MPI_Finalize(); |
||||
|
} |
@ -0,0 +1,242 @@ |
|||||
|
#include <stdio.h> |
||||
|
#include <stdlib.h> |
||||
|
#include <math.h> |
||||
|
|
||||
|
#include "knnMPIBlockingDeclarations.h" |
||||
|
#include "mpi.h" |
||||
|
|
||||
|
void getArguments(int argc, char** argv){ |
||||
|
if (argc != 6) { |
||||
|
printf("Usage: %s p d k filename\nwhere:\n", argv[0]); |
||||
|
printf("\tp is the the number of points\n"); |
||||
|
printf("\td is the number of dimensions of each point\n"); |
||||
|
printf("\tk is the number of neighbors to search for\n"); |
||||
|
printf("\tdf is the filename of the dataset file\n"); |
||||
|
printf("\ttf is the filename of the dataset file\n"); |
||||
|
abExit(1); |
||||
|
} |
||||
|
numberOfPoints = atoi(argv[1]); |
||||
|
numberOfDimensions = atoi(argv[2]); |
||||
|
numberOfNeighbors = atoi(argv[3]); |
||||
|
if (numberOfNeighbors >= numberOfPoints) { |
||||
|
numberOfNeighbors = numberOfPoints - 1; |
||||
|
} |
||||
|
pointsFilename = argv[4]; |
||||
|
testFilename = argv[5]; |
||||
|
} |
||||
|
|
||||
|
void init(double ***pointsArray, double ***inBuffer, double ***outBuffer |
||||
|
, neighbor ***sortedNeighborsArray, int chunksize, int offset){ |
||||
|
//Allocates memory for points array
|
||||
|
*pointsArray = cMalloc(chunksize, numberOfDimensions); |
||||
|
//Allocates memory for the buffer storing points coming from another process
|
||||
|
*inBuffer = cMalloc(chunksize, numberOfDimensions); |
||||
|
//Allocates memory for the buffer storing points going out to another process
|
||||
|
*outBuffer = cMalloc(chunksize, numberOfDimensions); |
||||
|
|
||||
|
//Allocates memory for neighbors array
|
||||
|
if ( (*sortedNeighborsArray = (neighbor**)(malloc((sizeof(neighbor *)) * chunksize))) != NULL ){ |
||||
|
for (int row = 0; row < chunksize; ++row){ |
||||
|
if ( ( (*sortedNeighborsArray)[row] |
||||
|
= (neighbor*)(malloc((sizeof(neighbor)) * numberOfNeighbors)) ) == NULL ){ |
||||
|
printf("Error allocating memory\n"); |
||||
|
abExit(1); |
||||
|
} |
||||
|
} |
||||
|
} else { |
||||
|
printf("Error allocating memory\n"); |
||||
|
abExit(1); |
||||
|
} |
||||
|
|
||||
|
//Reads coordinates from the file
|
||||
|
if (readPointsArrayFromFile(pointsArray, chunksize, offset)){ |
||||
|
abExit(1); |
||||
|
} |
||||
|
|
||||
|
//Initializes neighbors array distances and ID's to -1
|
||||
|
for (int point=0; point<chunksize; ++point){ |
||||
|
for(int neighbor=0; neighbor<numberOfNeighbors; ++neighbor){ |
||||
|
(*sortedNeighborsArray)[point][neighbor].distance = -1; |
||||
|
(*sortedNeighborsArray)[point][neighbor].neighborId = -1; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
double **cMalloc(int rows, int columns){ |
||||
|
double **array; |
||||
|
//allocates a continuous block of memory
|
||||
|
double *tempArray = (double *)calloc(rows * columns, sizeof(double)); |
||||
|
if (tempArray == NULL){ |
||||
|
printf("Error allocating memory\n"); |
||||
|
abExit(1); |
||||
|
} |
||||
|
|
||||
|
//creates pointers to each row and column for easy indexing
|
||||
|
if ((array = ((double**)(malloc((sizeof(double *)) * rows)))) != NULL){ |
||||
|
for (int row = 0; row < rows; ++row){ |
||||
|
array[row] = &(tempArray[columns * row]); |
||||
|
} |
||||
|
} else { |
||||
|
printf("Error allocating memory\n"); |
||||
|
abExit(1); |
||||
|
} |
||||
|
|
||||
|
return array; |
||||
|
} |
||||
|
|
||||
|
int readPointsArrayFromFile(double ***array, int chunksize, int offset){ |
||||
|
FILE *pointsBinaryFile = fopen(pointsFilename, "rb"); |
||||
|
|
||||
|
if (pointsBinaryFile == NULL){ |
||||
|
printf("Couldn't open points file.\n"); |
||||
|
return 1; |
||||
|
} |
||||
|
if (offset && fseek(pointsBinaryFile, offset * sizeof(double), SEEK_SET)){ |
||||
|
printf("Error reading the file. Quitting.\n"); |
||||
|
abExit(0); |
||||
|
} |
||||
|
for (int point=0; point<chunksize; ++point){ |
||||
|
if ( fread((*array)[point], sizeof(double), numberOfDimensions, pointsBinaryFile) |
||||
|
!= numberOfDimensions ){ |
||||
|
if(feof(pointsBinaryFile)){ |
||||
|
printf("Premature end of file reached.\n"); |
||||
|
} else{ |
||||
|
printf("Error reading points file."); |
||||
|
} |
||||
|
fclose(pointsBinaryFile); |
||||
|
return 1; |
||||
|
} |
||||
|
} |
||||
|
fclose(pointsBinaryFile); |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
void printArray(int rows, int columns, double ***array){ |
||||
|
for (int row=0; row<rows; ++row){ |
||||
|
for (int column=0; column<columns; ++column){ |
||||
|
printf("[%d][%d] = %f\n", row, column, (*array)[row][column]); |
||||
|
} |
||||
|
printf("\n"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void calculateDistances(double ***firstPointsSet, double ***secondPointsSet |
||||
|
, neighbor ***sortedNeighborsArray, int chunksize, int myOffset, int indexOffset){ |
||||
|
for (int firstPoint=0; firstPoint<chunksize; ++firstPoint){ |
||||
|
for (int secondPoint=0; secondPoint<chunksize; ++secondPoint){ |
||||
|
if (myOffset + firstPoint == indexOffset + secondPoint){ |
||||
|
continue; |
||||
|
} |
||||
|
double distance = 0; |
||||
|
for (int dimensionIndex=0; dimensionIndex<numberOfDimensions; ++dimensionIndex){ |
||||
|
double tmpDiff = (*firstPointsSet)[firstPoint][dimensionIndex] |
||||
|
- (*secondPointsSet)[secondPoint][dimensionIndex]; |
||||
|
distance += tmpDiff * tmpDiff; |
||||
|
} |
||||
|
addDistanceAndShift(sortedNeighborsArray, firstPoint, indexOffset + secondPoint |
||||
|
, distance); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void addDistanceAndShift(neighbor ***sortedNeighborsArray, int firstPointId, int secondPointId |
||||
|
, double pointsDistance){ |
||||
|
for (int arrayIndex=0; arrayIndex<numberOfNeighbors; ++arrayIndex){ |
||||
|
//Gets distance stored in the array for this index
|
||||
|
double thisNeighborDistance = (*sortedNeighborsArray)[firstPointId][arrayIndex].distance; |
||||
|
|
||||
|
if (thisNeighborDistance == -1){ //Loop reached the end of the array
|
||||
|
(*sortedNeighborsArray)[firstPointId][arrayIndex].distance = pointsDistance; |
||||
|
(*sortedNeighborsArray)[firstPointId][arrayIndex].neighborId = secondPointId; |
||||
|
break; |
||||
|
} else if (thisNeighborDistance > pointsDistance){ |
||||
|
//Distance at the this index is greater than the distance being inserted
|
||||
|
//Shifts right all non empty columns holding distances lower than pointsDistance
|
||||
|
for (int moveColumn=numberOfNeighbors-2; moveColumn>=arrayIndex; --moveColumn){ |
||||
|
double tempDistance = (*sortedNeighborsArray)[firstPointId][moveColumn].distance; |
||||
|
if (tempDistance == -1){ //Skips empty columns
|
||||
|
continue; |
||||
|
} |
||||
|
(*sortedNeighborsArray)[firstPointId][moveColumn+1].distance = tempDistance; |
||||
|
(*sortedNeighborsArray)[firstPointId][moveColumn+1].neighborId |
||||
|
= (*sortedNeighborsArray)[firstPointId][moveColumn].neighborId; |
||||
|
} |
||||
|
//Inserts pointsDistance in the space created after shifting
|
||||
|
(*sortedNeighborsArray)[firstPointId][arrayIndex].distance = pointsDistance; |
||||
|
(*sortedNeighborsArray)[firstPointId][arrayIndex].neighborId = secondPointId; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void swapPointers(double ***firstArray, double ***secondArray){ |
||||
|
double **tempPtr = *firstArray; |
||||
|
*firstArray = *secondArray; |
||||
|
*secondArray = tempPtr; |
||||
|
} |
||||
|
|
||||
|
int test(neighbor ***sortedNeighborsArray, int chunksize, int offset, char *testFilename){ |
||||
|
FILE *testFile = fopen(testFilename, "r"); |
||||
|
char *discarded = NULL; |
||||
|
size_t n = 0; |
||||
|
|
||||
|
if (testFile == NULL){ |
||||
|
printf("Couldn't open test file.\n"); |
||||
|
perror("fopen"); |
||||
|
return 1; |
||||
|
} |
||||
|
if (offset){ |
||||
|
for (int line=0; line<offset; ++line){ |
||||
|
if (getline(&discarded, &n, testFile) == -1){ |
||||
|
perror("Error reading test file"); |
||||
|
return 1; |
||||
|
} |
||||
|
n = 0; |
||||
|
} |
||||
|
free(discarded); |
||||
|
} |
||||
|
for (int point=0; point<chunksize; ++point){ |
||||
|
for (int i=0; i<numberOfNeighbors; ++i){ |
||||
|
int tempID = 0; |
||||
|
if (fscanf(testFile, "%d,", &tempID) == EOF){ |
||||
|
printf("Premature end of file reached.\n"); |
||||
|
fclose(testFile); |
||||
|
return 1; |
||||
|
} |
||||
|
if ((*sortedNeighborsArray)[point][i].neighborId != tempID - 1){ //-1 because f@ck matlab
|
||||
|
fclose(testFile); |
||||
|
return 1; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
fclose(testFile); |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
void cleanUp(double ***pointsArray, double ***inBuffer, double ***outBuffer |
||||
|
, neighbor ***sortedNeighborsArray, int chunksize){ |
||||
|
free((*pointsArray)[0]); |
||||
|
free(*pointsArray); |
||||
|
|
||||
|
free((*inBuffer)[0]); |
||||
|
free(*inBuffer); |
||||
|
|
||||
|
free((*outBuffer)[0]); |
||||
|
free(*outBuffer); |
||||
|
|
||||
|
for (int row=0; row<chunksize; ++row){ |
||||
|
free((*sortedNeighborsArray)[row]); |
||||
|
} |
||||
|
free(*sortedNeighborsArray); |
||||
|
} |
||||
|
|
||||
|
void abExit(int exitCode){ |
||||
|
int initialized = 0; |
||||
|
MPI_Initialized(&initialized); |
||||
|
if (initialized){ |
||||
|
MPI_Abort(MPI_COMM_WORLD, -1); |
||||
|
} |
||||
|
exit(0); |
||||
|
} |
@ -0,0 +1,89 @@ |
|||||
|
#ifndef KNNMPIBLOCKINGFUNCTIONDECLARATION_H_ /* Include guard */ |
||||
|
#define KNNMPIBLOCKINGFUNCTIONDECLARATION_H_ |
||||
|
|
||||
|
/* Constants definitions */ |
||||
|
#define MASTER 0 //task id of the master process
|
||||
|
|
||||
|
/* Structs */ |
||||
|
typedef struct neighbor{ //simple struct defining a point's neighbor
|
||||
|
double distance; //distance between the two neighbors (points)
|
||||
|
int neighborId; //index of the neighbor in the (complete) array of points
|
||||
|
} neighbor; |
||||
|
|
||||
|
/* Global variables */ |
||||
|
extern int numberOfPoints; //number of the points knn should run for
|
||||
|
extern int numberOfDimensions; //number of dimensions of each point
|
||||
|
extern int numberOfNeighbors; //number of nearest neighbors knn should find for each point
|
||||
|
extern char *pointsFilename; //name of the binary file storing the coordinates of points
|
||||
|
extern char *testFilename; //name of binary file storing correct neighbors IDs array
|
||||
|
|
||||
|
/* Functions declaration */ |
||||
|
|
||||
|
//Function getArguments is used to parse arguments provided to main
|
||||
|
void getArguments(int argc //arguments count
|
||||
|
, char** argv); //arguments array
|
||||
|
|
||||
|
//Function init allocates memory for the arrays used and initializes them
|
||||
|
void init(double ***pointsArray //pointer to the array of points
|
||||
|
, double ***inBuffer //pointer to the array used as input buffer for mpi
|
||||
|
, double ***outBuffer //pointer to the array used as output buffer for mpi
|
||||
|
, neighbor ***sortedNeighborsArray //pointer to the array holding the distances and ID's
|
||||
|
, int chunksize //number of rows (points) to be allocated
|
||||
|
, int offset); //process offset used when reading points from the file
|
||||
|
|
||||
|
//Function cMalloc allocates and returns a single block of continuous memory which can
|
||||
|
//be indexed like a regular array, e.g. array[row][column]
|
||||
|
double **cMalloc(int rows //number of rows to be allocated
|
||||
|
, int columns); //number of columns to be allocated
|
||||
|
|
||||
|
//Function readPointsArrayFromFile reads the coordinates of the points from a file and stores them
|
||||
|
//in an array
|
||||
|
int readPointsArrayFromFile(double ***array //array that will hold the coordinates of the points
|
||||
|
, int chunksize //number of rows (points) to be read
|
||||
|
, int offset); //offset from which reading will start
|
||||
|
|
||||
|
//Function printArray iterates the values of an array printing them
|
||||
|
void printArray(int rows //number of array's rows
|
||||
|
, int columns //number of array's columns
|
||||
|
, double ***array); //array to be printed
|
||||
|
|
||||
|
//Function calculateDistances calculates the distances between all points in two different sets and
|
||||
|
//adds the distance to sortedNeighborsArray
|
||||
|
void calculateDistances(double ***firstPointsSet //first pool of points coordinates
|
||||
|
, double ***secondPointsSet //second pool of points coordinates
|
||||
|
, neighbor ***sortedNeighborsArray //array that holds the distances
|
||||
|
, int chunksize //number of points
|
||||
|
, int myOffset //offset used for ID's of first pool's points
|
||||
|
, int indexOffset); //offset used for ID's of seconds pool's points
|
||||
|
|
||||
|
//Function addDistanceAndShift searches an array of neighbors (struct) for an index holding either
|
||||
|
//an empty distance or a distance that is greater than the one that came in the arguments
|
||||
|
//(pointsDistance), shifts "right" one time all values of the array after this index and fills the
|
||||
|
//empty position created after shifting with the one that came in the arguments (pointsDistance)
|
||||
|
void addDistanceAndShift(neighbor ***sortedNeighborsArray //array that holds the distances
|
||||
|
, int firstPointId //ID of the first point
|
||||
|
, int secondPointId //ID of the second point
|
||||
|
, double pointsDistance); //distance between the two points
|
||||
|
|
||||
|
//Function swapPointers swaps the memory blocks pointed to by two pointers
|
||||
|
void swapPointers(double ***firstArray //first memory block
|
||||
|
, double ***secondArray); //second memory block
|
||||
|
|
||||
|
//Function test checks the validity of the solution based on correct results previously generated
|
||||
|
//and stored in a text file
|
||||
|
int test(neighbor ***sortedNeighborsArray //array that holds the IDs
|
||||
|
, int chunksize //number of points
|
||||
|
, int offset //process offset
|
||||
|
, char *testFilename); //name of text file storing correct neighbors IDs array
|
||||
|
|
||||
|
//Function cleanUp frees all memory previously allocated
|
||||
|
void cleanUp(double ***pointsArray //points array pointer
|
||||
|
, double ***inBuffer //input buffer pointer
|
||||
|
, double ***outBuffer //output buffer pointer
|
||||
|
, neighbor ***sortedNeighborsArray //distances array pointer
|
||||
|
, int chunksize); //number of rows (points)
|
||||
|
|
||||
|
//Function abExit exits the program after checking for mpi initialization
|
||||
|
void abExit(int exitCode); //exit code to exit with
|
||||
|
|
||||
|
#endif // KNNMPIBLOCKINGFUNCTIONDECLARATION_H_
|
Binary file not shown.
@ -0,0 +1,21 @@ |
|||||
|
TARGET=KnnMPIBlockingTimeOptimized |
||||
|
CC=mpicc |
||||
|
CFLAGS=-Wall -O3 -std=gnu99 -I. |
||||
|
OBJ=knnMPIBlocking.o knnMPIBlockingDeclarations.o |
||||
|
DEPS=knnMPIBlockingDeclarations.h |
||||
|
|
||||
|
.PHONY: default all clean |
||||
|
|
||||
|
default: $(TARGET) |
||||
|
all: default |
||||
|
|
||||
|
%.o: %.c $(DEPS) |
||||
|
$(CC) -c -o $@ $< $(CFLAGS) |
||||
|
|
||||
|
.PRECIOUS: $(TARGET) $(OBJ) |
||||
|
|
||||
|
$(TARGET): $(OBJ) |
||||
|
$(CC) -o $@ $^ $(CFLAGS) |
||||
|
|
||||
|
clean: |
||||
|
$(RM) *.o *~ |
@ -0,0 +1,162 @@ |
|||||
|
#include <stdio.h> |
||||
|
#include <stdlib.h> |
||||
|
#include <sys/time.h> |
||||
|
|
||||
|
#include "knnMPIBlockingDeclarations.h" |
||||
|
#include "mpi.h" |
||||
|
|
||||
|
/* Structs */ |
||||
|
struct timeval startwtime, endwtime |
||||
|
, commStartWTime, commEndWTime |
||||
|
, calcStartWTime, calcEndWTime; |
||||
|
|
||||
|
/* Global variables */ |
||||
|
int numberOfPoints = 0, numberOfDimensions = 0, numberOfNeighbors = 0, k = 0; |
||||
|
char *pointsFilename = NULL, *testFilename = NULL; |
||||
|
double seq_time = 0; |
||||
|
|
||||
|
/* Main */ |
||||
|
int main(int argc, char **argv){ |
||||
|
int numberOfTasks = 0, taskId = 0, chunksize = 0, myOffset = 0, destination = 0, source = 0; |
||||
|
double **myPoints, **inBuffer, **outBuffer, commTimeSum = 0, calcTimeSum = 0; |
||||
|
neighbor **sortedNeighborsArray; |
||||
|
MPI_Status status; |
||||
|
|
||||
|
getArguments(argc, argv); |
||||
|
|
||||
|
//Initializes mpi and necessary variables
|
||||
|
MPI_Init(&argc, &argv); |
||||
|
MPI_Comm_size(MPI_COMM_WORLD, &numberOfTasks); |
||||
|
if (numberOfPoints % numberOfTasks != 0){ |
||||
|
printf("Quitting. Number of points must be divisible by number of MPI tasks.\n"); |
||||
|
abExit(0); |
||||
|
} |
||||
|
MPI_Comm_rank(MPI_COMM_WORLD, &taskId); |
||||
|
|
||||
|
chunksize = numberOfPoints / numberOfTasks; //number of points each task has
|
||||
|
myOffset = taskId * chunksize; //this task's offset from (complete) point's array start
|
||||
|
destination = taskId + 1; //this task's destination task id for sending messages
|
||||
|
if (destination >= numberOfTasks){ |
||||
|
destination = 0; |
||||
|
} |
||||
|
source= taskId - 1; //this task's source task id for receiving messages
|
||||
|
if (source < 0){ |
||||
|
source = numberOfTasks - 1; |
||||
|
} |
||||
|
|
||||
|
init(&myPoints, &inBuffer, &outBuffer, &sortedNeighborsArray, chunksize |
||||
|
, myOffset * numberOfDimensions); |
||||
|
|
||||
|
MPI_Barrier(MPI_COMM_WORLD); |
||||
|
if (taskId == MASTER){ |
||||
|
gettimeofday(&startwtime, NULL); |
||||
|
} |
||||
|
|
||||
|
gettimeofday(&calcStartWTime, NULL); |
||||
|
|
||||
|
//Calculates distances between task's own points
|
||||
|
calculateDistances(&myPoints, &myPoints, &sortedNeighborsArray, chunksize, myOffset |
||||
|
, taskId * chunksize); |
||||
|
|
||||
|
gettimeofday(&calcEndWTime, NULL); |
||||
|
calcTimeSum += (double)((calcEndWTime.tv_usec - calcStartWTime.tv_usec)/1.0e6 |
||||
|
+ calcEndWTime.tv_sec - calcStartWTime.tv_sec); |
||||
|
|
||||
|
for (int chunk=0; chunk<numberOfTasks-1; ++chunk){ |
||||
|
gettimeofday(&commStartWTime, NULL); |
||||
|
//sends-receives points array blocks
|
||||
|
if (taskId == MASTER){ |
||||
|
//master task sends first to avoid deadlocks
|
||||
|
MPI_Send((chunk == 0) //if this is the first loop
|
||||
|
? &(myPoints[0][0]) //send this task's points
|
||||
|
: &(outBuffer[0][0]) //else send the points received from previous loop
|
||||
|
, chunksize * numberOfDimensions, MPI_DOUBLE, destination, taskId, MPI_COMM_WORLD); |
||||
|
MPI_Recv(&(inBuffer[0][0]), chunksize * numberOfDimensions, MPI_DOUBLE, source, source |
||||
|
, MPI_COMM_WORLD, &status); |
||||
|
} else { |
||||
|
//other tasks receive first
|
||||
|
MPI_Recv(&(inBuffer[0][0]), chunksize * numberOfDimensions, MPI_DOUBLE, source, source |
||||
|
, MPI_COMM_WORLD, &status); |
||||
|
MPI_Send((chunk == 0) //if this is the first loop
|
||||
|
? &(myPoints[0][0]) //send this task's points
|
||||
|
: &(outBuffer[0][0]) //else send the points received from previous loop
|
||||
|
, chunksize * numberOfDimensions, MPI_DOUBLE, destination, taskId, MPI_COMM_WORLD); |
||||
|
} |
||||
|
gettimeofday(&commEndWTime, NULL); |
||||
|
commTimeSum += (double)((commEndWTime.tv_usec - commStartWTime.tv_usec)/1.0e6 |
||||
|
+ commEndWTime.tv_sec - commStartWTime.tv_sec); |
||||
|
|
||||
|
//offset, the task that sent new points block has from (complete) point's array start
|
||||
|
//used for storing the correct neighbor id's in neighbors array
|
||||
|
int offset = source - chunk; |
||||
|
if (offset < 0){ |
||||
|
offset += numberOfTasks; |
||||
|
} |
||||
|
offset *= chunksize; |
||||
|
|
||||
|
gettimeofday(&calcStartWTime, NULL); |
||||
|
|
||||
|
//calculates distances between task's points and new points received
|
||||
|
calculateDistances(&myPoints, &inBuffer, &sortedNeighborsArray, chunksize, myOffset |
||||
|
, offset); |
||||
|
|
||||
|
gettimeofday(&calcEndWTime, NULL); |
||||
|
calcTimeSum += (double)((calcEndWTime.tv_usec - calcStartWTime.tv_usec)/1.0e6 |
||||
|
+ calcEndWTime.tv_sec - calcStartWTime.tv_sec); |
||||
|
|
||||
|
swapPointers(&inBuffer, &outBuffer); |
||||
|
} |
||||
|
|
||||
|
gettimeofday(&calcStartWTime, NULL); |
||||
|
|
||||
|
for (int point=0; point<chunksize; ++point){ |
||||
|
qsort (sortedNeighborsArray[point], numberOfNeighbors, sizeof(neighbor), compare); |
||||
|
} |
||||
|
|
||||
|
gettimeofday(&calcEndWTime, NULL); |
||||
|
calcTimeSum += (double)((calcEndWTime.tv_usec - calcStartWTime.tv_usec)/1.0e6 |
||||
|
+ calcEndWTime.tv_sec - calcStartWTime.tv_sec); |
||||
|
|
||||
|
if (test(&sortedNeighborsArray, chunksize, myOffset, testFilename)){ |
||||
|
printf("Validity check failed for task %d!\n", taskId); |
||||
|
} else { |
||||
|
printf("Validity check success for task %d!\n", taskId); |
||||
|
} |
||||
|
|
||||
|
MPI_Barrier(MPI_COMM_WORLD); |
||||
|
if (taskId == MASTER){ |
||||
|
gettimeofday(&endwtime, NULL); |
||||
|
seq_time = (double)((endwtime.tv_usec - startwtime.tv_usec)/1.0e6 |
||||
|
+ endwtime.tv_sec - startwtime.tv_sec); |
||||
|
|
||||
|
printf("Wall clock time = %f\n\n", seq_time); |
||||
|
} |
||||
|
|
||||
|
if (taskId == MASTER){ |
||||
|
printf("Number of points = %d\n", numberOfPoints); |
||||
|
printf("Number of dimensions = %d\n", numberOfDimensions); |
||||
|
printf("Number of neighbors = %d\n", numberOfNeighbors); |
||||
|
printf("Number of tasks = %d\n", numberOfTasks); |
||||
|
} |
||||
|
for(int i=0; i<numberOfTasks; ++i) { |
||||
|
MPI_Barrier(MPI_COMM_WORLD); |
||||
|
if (i == taskId) { |
||||
|
printf("Task %d communications time sum = %f\n", taskId, commTimeSum); |
||||
|
printf("Task %d calculations time sum = %f\n", taskId, calcTimeSum); |
||||
|
|
||||
|
/*
|
||||
|
Uncomment to print the results |
||||
|
*/ |
||||
|
/*for (int x=0; x<chunksize; ++x){
|
||||
|
for (int y=0; y<numberOfNeighbors; ++y){ |
||||
|
printf("%d to %d = %f\n", x + taskId * chunksize |
||||
|
, sortedNeighborsArray[x][y].neighborId, sortedNeighborsArray[x][y].distance); |
||||
|
} |
||||
|
printf("\n"); |
||||
|
}*/ |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
cleanUp(&myPoints, &inBuffer, &outBuffer, &sortedNeighborsArray, chunksize); |
||||
|
MPI_Finalize(); |
||||
|
} |
@ -0,0 +1,237 @@ |
|||||
|
#include <stdio.h> |
||||
|
#include <stdlib.h> |
||||
|
#include <math.h> |
||||
|
|
||||
|
#include "knnMPIBlockingDeclarations.h" |
||||
|
#include "mpi.h" |
||||
|
|
||||
|
void getArguments(int argc, char** argv){ |
||||
|
if (argc != 6) { |
||||
|
printf("Usage: %s p d k filename\nwhere:\n", argv[0]); |
||||
|
printf("\tp is the the number of points\n"); |
||||
|
printf("\td is the number of dimensions of each point\n"); |
||||
|
printf("\tk is the number of neighbors to search for\n"); |
||||
|
printf("\tdf is the filename of the dataset file\n"); |
||||
|
printf("\ttf is the filename of the dataset file\n"); |
||||
|
abExit(1); |
||||
|
} |
||||
|
numberOfPoints = atoi(argv[1]); |
||||
|
numberOfDimensions = atoi(argv[2]); |
||||
|
numberOfNeighbors = numberOfPoints - 1; |
||||
|
k = atoi(argv[3]); |
||||
|
if (k >= numberOfPoints){ |
||||
|
k = numberOfPoints - 1; |
||||
|
} |
||||
|
pointsFilename = argv[4]; |
||||
|
testFilename = argv[5]; |
||||
|
} |
||||
|
|
||||
|
void init(double ***pointsArray, double ***inBuffer, double ***outBuffer |
||||
|
, neighbor ***sortedNeighborsArray, int chunksize, int offset){ |
||||
|
//Allocates memory for points array
|
||||
|
*pointsArray = cMalloc(chunksize, numberOfDimensions); |
||||
|
//Allocates memory for the buffer storing points coming from another process
|
||||
|
*inBuffer = cMalloc(chunksize, numberOfDimensions); |
||||
|
//Allocates memory for the buffer storing points going out to another process
|
||||
|
*outBuffer = cMalloc(chunksize, numberOfDimensions); |
||||
|
|
||||
|
//Allocates memory for neighbors array
|
||||
|
if ( (*sortedNeighborsArray = (neighbor**)(malloc((sizeof(neighbor *)) * chunksize))) != NULL ){ |
||||
|
for (int row = 0; row < chunksize; ++row){ |
||||
|
if ( ( (*sortedNeighborsArray)[row] |
||||
|
= (neighbor*)(malloc((sizeof(neighbor)) * numberOfNeighbors)) ) == NULL ){ |
||||
|
printf("Error allocating memory\n"); |
||||
|
abExit(1); |
||||
|
} |
||||
|
} |
||||
|
} else { |
||||
|
printf("Error allocating memory\n"); |
||||
|
abExit(1); |
||||
|
} |
||||
|
|
||||
|
//Reads coordinates from the file
|
||||
|
if (readPointsArrayFromFile(pointsArray, chunksize, offset)){ |
||||
|
abExit(1); |
||||
|
} |
||||
|
|
||||
|
//Initializes neighbors array distances and ID's to -1
|
||||
|
for (int point=0; point<chunksize; ++point){ |
||||
|
for(int neighbor=0; neighbor<numberOfNeighbors; ++neighbor){ |
||||
|
(*sortedNeighborsArray)[point][neighbor].distance = -1; |
||||
|
(*sortedNeighborsArray)[point][neighbor].neighborId = -1; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
double **cMalloc(int rows, int columns){ |
||||
|
double **array; |
||||
|
//allocates a continuous block of memory
|
||||
|
double *tempArray = (double *)calloc(rows * columns, sizeof(double)); |
||||
|
if (tempArray == NULL){ |
||||
|
printf("Error allocating memory\n"); |
||||
|
abExit(1); |
||||
|
} |
||||
|
|
||||
|
//creates pointers to each row and column for easy indexing
|
||||
|
if ((array = ((double**)(malloc((sizeof(double *)) * rows)))) != NULL){ |
||||
|
for (int row = 0; row < rows; ++row){ |
||||
|
array[row] = &(tempArray[columns * row]); |
||||
|
} |
||||
|
} else { |
||||
|
printf("Error allocating memory\n"); |
||||
|
abExit(1); |
||||
|
} |
||||
|
|
||||
|
return array; |
||||
|
} |
||||
|
|
||||
|
int readPointsArrayFromFile(double ***array, int chunksize, int offset){ |
||||
|
FILE *pointsBinaryFile = fopen(pointsFilename, "rb"); |
||||
|
|
||||
|
if (pointsBinaryFile == NULL){ |
||||
|
printf("Couldn't open points file.\n"); |
||||
|
return 1; |
||||
|
} |
||||
|
if (fseek(pointsBinaryFile, offset * sizeof(double), SEEK_SET)){ |
||||
|
printf("Error reading the file. Quitting.\n"); |
||||
|
abExit(0); |
||||
|
} |
||||
|
for (int point=0; point<chunksize; ++point){ |
||||
|
if ( fread((*array)[point], sizeof(double), numberOfDimensions, pointsBinaryFile) |
||||
|
!= numberOfDimensions ){ |
||||
|
if(feof(pointsBinaryFile)){ |
||||
|
printf("Premature end of file reached.\n"); |
||||
|
} else{ |
||||
|
printf("Error reading points file."); |
||||
|
} |
||||
|
fclose(pointsBinaryFile); |
||||
|
return 1; |
||||
|
} |
||||
|
} |
||||
|
fclose(pointsBinaryFile); |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
void printArray(int rows, int columns, double ***array){ |
||||
|
for (int row=0; row<rows; ++row){ |
||||
|
for (int column=0; column<columns; ++column){ |
||||
|
printf("[%d][%d] = %f\n", row, column, (*array)[row][column]); |
||||
|
} |
||||
|
printf("\n"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void calculateDistances(double ***firstPointsSet, double ***secondPointsSet |
||||
|
, neighbor ***sortedNeighborsArray, int chunksize, int myOffset, int indexOffset){ |
||||
|
for (int firstPoint=0; firstPoint<chunksize; ++firstPoint){ |
||||
|
for (int secondPoint=0; secondPoint<chunksize; ++secondPoint){ |
||||
|
if (myOffset + firstPoint == indexOffset + secondPoint){ |
||||
|
continue; |
||||
|
} |
||||
|
double distance = 0; |
||||
|
for (int dimensionIndex=0; dimensionIndex<numberOfDimensions; ++dimensionIndex){ |
||||
|
double tmpDiff = (*firstPointsSet)[firstPoint][dimensionIndex] |
||||
|
- (*secondPointsSet)[secondPoint][dimensionIndex]; |
||||
|
distance += tmpDiff * tmpDiff; |
||||
|
} |
||||
|
addDistance(sortedNeighborsArray, firstPoint, myOffset + firstPoint |
||||
|
, indexOffset + secondPoint, distance); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void addDistance(neighbor ***sortedNeighborsArray, int firstPointIndex, int firstPointId |
||||
|
, int secondPointId, double pointsDistance){ |
||||
|
//Determines actual index in which the distance will be added
|
||||
|
int insertIndex = secondPointId; |
||||
|
if (secondPointId > firstPointId){ |
||||
|
--insertIndex; |
||||
|
} |
||||
|
|
||||
|
(*sortedNeighborsArray)[firstPointIndex][insertIndex].distance = pointsDistance; |
||||
|
(*sortedNeighborsArray)[firstPointIndex][insertIndex].neighborId = secondPointId; |
||||
|
} |
||||
|
|
||||
|
int compare (const void *a, const void *b){ |
||||
|
//Casts arguments to pointers to neighbors
|
||||
|
const neighbor *neighborA = (neighbor*) a; |
||||
|
const neighbor *neighborB = (neighbor*) b; |
||||
|
|
||||
|
if (neighborA->distance == neighborB->distance){ |
||||
|
return 0; |
||||
|
} else{ |
||||
|
return neighborA->distance > neighborB->distance ? 1 : -1; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void swapPointers(double ***firstArray, double ***secondArray){ |
||||
|
double **tempPtr = *firstArray; |
||||
|
*firstArray = *secondArray; |
||||
|
*secondArray = tempPtr; |
||||
|
} |
||||
|
|
||||
|
int test(neighbor ***sortedNeighborsArray, int chunksize, int offset, char *testFilename){ |
||||
|
FILE *testFile = fopen(testFilename, "r"); |
||||
|
char *discarded = NULL; |
||||
|
size_t n = 0; |
||||
|
|
||||
|
if (testFile == NULL){ |
||||
|
printf("Couldn't open test file.\n"); |
||||
|
perror("fopen"); |
||||
|
return 1; |
||||
|
} |
||||
|
if (offset){ |
||||
|
for (int line=0; line<offset; ++line){ |
||||
|
if (getline(&discarded, &n, testFile) == -1){ |
||||
|
perror("Error reading test file"); |
||||
|
return 1; |
||||
|
} |
||||
|
n = 0; |
||||
|
} |
||||
|
free(discarded); |
||||
|
} |
||||
|
for (int point=0; point<chunksize; ++point){ |
||||
|
for (int i=0; i<k; ++i){ |
||||
|
int tempID = 0; |
||||
|
if (fscanf(testFile, "%d,", &tempID) == EOF){ |
||||
|
printf("Premature end of file reached.\n"); |
||||
|
fclose(testFile); |
||||
|
return 1; |
||||
|
} |
||||
|
if ((*sortedNeighborsArray)[point][i].neighborId != tempID - 1){ //-1 because f@ck matlab
|
||||
|
fclose(testFile); |
||||
|
return 1; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
fclose(testFile); |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
void cleanUp(double ***pointsArray, double ***inBuffer, double ***outBuffer |
||||
|
, neighbor ***sortedNeighborsArray, int chunksize){ |
||||
|
free((*pointsArray)[0]); |
||||
|
free(*pointsArray); |
||||
|
|
||||
|
free((*inBuffer)[0]); |
||||
|
free(*inBuffer); |
||||
|
|
||||
|
free((*outBuffer)[0]); |
||||
|
free(*outBuffer); |
||||
|
|
||||
|
for (int row=0; row<chunksize; ++row){ |
||||
|
free((*sortedNeighborsArray)[row]); |
||||
|
} |
||||
|
free(*sortedNeighborsArray); |
||||
|
} |
||||
|
|
||||
|
void abExit(int exitCode){ |
||||
|
int initialized = 0; |
||||
|
MPI_Initialized(&initialized); |
||||
|
if (initialized){ |
||||
|
MPI_Abort(MPI_COMM_WORLD, -1); |
||||
|
} |
||||
|
exit(0); |
||||
|
} |
@ -0,0 +1,93 @@ |
|||||
|
#ifndef KNNMPIBLOCKINGFUNCTIONDECLARATION_H_ /* Include guard */ |
||||
|
#define KNNMPIBLOCKINGFUNCTIONDECLARATION_H_ |
||||
|
|
||||
|
/* Constants definitions */ |
||||
|
#define MASTER 0 //task id of the master process
|
||||
|
|
||||
|
/* Structs */ |
||||
|
typedef struct neighbor{ //simple struct defining a point's neighbor
|
||||
|
double distance; //distance between the two neighbors (points)
|
||||
|
int neighborId; //index of the neighbor in the (complete) array of points
|
||||
|
} neighbor; |
||||
|
|
||||
|
/* Global variables */ |
||||
|
extern int numberOfPoints; //number of the points knn should run for
|
||||
|
extern int numberOfDimensions; //number of dimensions of each point
|
||||
|
extern int numberOfNeighbors; //number of nearest neighbors knn should find for each point
|
||||
|
extern int k; //number of nearest neighbors requested by the user
|
||||
|
extern char *pointsFilename; //name of the binary file storing the coordinates of points
|
||||
|
extern char *testFilename; //name of binary file storing correct neighbors IDs array
|
||||
|
|
||||
|
/* Functions declaration */ |
||||
|
|
||||
|
//Function getArguments is used to parse arguments provided to main
|
||||
|
void getArguments(int argc //arguments count
|
||||
|
, char** argv); //arguments array
|
||||
|
|
||||
|
//Function init allocates memory for the arrays used and initializes them
|
||||
|
void init(double ***pointsArray //pointer to the array of points
|
||||
|
, double ***inBuffer //pointer to the array used as input buffer for mpi
|
||||
|
, double ***outBuffer //pointer to the array used as output buffer for mpi
|
||||
|
, neighbor ***sortedNeighborsArray //pointer to the array holding the distances and ID's
|
||||
|
, int chunksize //number of rows (points) to be allocated
|
||||
|
, int offset); //process offset used when reading points from the file
|
||||
|
|
||||
|
//Function cMalloc allocates and returns a single block of continuous memory which can
|
||||
|
//be indexed like a regular array, e.g. array[row][column]
|
||||
|
double **cMalloc(int rows //number of rows to be allocated
|
||||
|
, int columns); //number of columns to be allocated
|
||||
|
|
||||
|
//Function readPointsArrayFromFile reads the coordinates of the points from a file and stores them
|
||||
|
//in an array
|
||||
|
int readPointsArrayFromFile(double ***array //array that will hold the coordinates of the points
|
||||
|
, int chunksize //number of rows (points) to be read
|
||||
|
, int offset); //offset from which reading will start
|
||||
|
|
||||
|
//Function printArray iterates the values of an array printing them
|
||||
|
void printArray(int rows //number of array's rows
|
||||
|
, int columns //number of array's columns
|
||||
|
, double ***array); //array to be printed
|
||||
|
|
||||
|
//Function calculateDistances calculates the distances between all points in two different sets and
|
||||
|
//adds the distance to sortedNeighborsArray
|
||||
|
void calculateDistances(double ***firstPointsSet //first pool of points coordinates
|
||||
|
, double ***secondPointsSet //second pool of points coordinates
|
||||
|
, neighbor ***sortedNeighborsArray //array that holds the distances
|
||||
|
, int chunksize //number of points
|
||||
|
, int myOffset //offset used for ID's of first pool's points
|
||||
|
, int indexOffset); //offset used for ID's of seconds pool's points
|
||||
|
|
||||
|
//Function addDistance adds distances to sorted neighbors array sorted by the ID of the neighbor
|
||||
|
void addDistance(neighbor ***sortedNeighborsArray //array that holds the distances
|
||||
|
, int firstPointIndex //Index of the first point in task's array
|
||||
|
, int firstPointId //ID of the first point
|
||||
|
, int secondPointId //ID of the second point
|
||||
|
, double pointsDistance); //distance between the two points
|
||||
|
|
||||
|
//Function compare compares two neighbors using their distance fields, returns 0 if distances are
|
||||
|
//equal, 1 if distance of first argument is greater and -1 otherwise
|
||||
|
int compare (const void *a //first neighbor
|
||||
|
, const void *b); //second neighbor
|
||||
|
|
||||
|
//Function swapPointers swaps the memory blocks pointed to by two pointers
|
||||
|
void swapPointers(double ***firstArray //first memory block
|
||||
|
, double ***secondArray); //second memory block
|
||||
|
|
||||
|
//Function test checks the validity of the solution based on correct results previously generated
|
||||
|
//and stored in a text file
|
||||
|
int test(neighbor ***sortedNeighborsArray //array that holds the IDs
|
||||
|
, int chunksize //number of points
|
||||
|
, int offset //process offset
|
||||
|
, char *testFilename); //name of text file storing correct neighbors IDs array
|
||||
|
|
||||
|
//Function cleanUp frees all memory previously allocated
|
||||
|
void cleanUp(double ***pointsArray //points array pointer
|
||||
|
, double ***inBuffer //input buffer pointer
|
||||
|
, double ***outBuffer //output buffer pointer
|
||||
|
, neighbor ***sortedNeighborsArray //distances array pointer
|
||||
|
, int chunksize); //number of rows (points)
|
||||
|
|
||||
|
//Function abExit exits the program after checking for mpi initialization
|
||||
|
void abExit(int exitCode); //exit code to exit with
|
||||
|
|
||||
|
#endif // KNNMPIBLOCKINGFUNCTIONDECLARATION_H_
|
@ -0,0 +1,21 @@ |
|||||
|
TARGET=KnnMPINonBlockingSpaceOptimized |
||||
|
CC=mpicc |
||||
|
CFLAGS=-Wall -O3 -std=gnu99 -I. |
||||
|
OBJ=knnMPINonBlocking.o knnMPINonBlockingDeclarations.o |
||||
|
DEPS=knnMPINonBlockingDeclarations.h |
||||
|
|
||||
|
.PHONY: default all clean |
||||
|
|
||||
|
default: $(TARGET) |
||||
|
all: default |
||||
|
|
||||
|
%.o: %.c $(DEPS) |
||||
|
$(CC) -c -o $@ $< $(CFLAGS) |
||||
|
|
||||
|
.PRECIOUS: $(TARGET) $(OBJ) |
||||
|
|
||||
|
$(TARGET): $(OBJ) |
||||
|
$(CC) -o $@ $^ $(CFLAGS) |
||||
|
|
||||
|
clean: |
||||
|
$(RM) *.o *~ |
@ -0,0 +1,138 @@ |
|||||
|
#include <stdio.h> |
||||
|
#include <sys/time.h> |
||||
|
|
||||
|
#include "knnMPINonBlockingDeclarations.h" |
||||
|
#include "mpi.h" |
||||
|
|
||||
|
/* Structs */ |
||||
|
struct timeval startwtime, endwtime |
||||
|
, calcStartWTime, calcEndWTime; |
||||
|
|
||||
|
/* Global variables */ |
||||
|
int numberOfPoints = 0, numberOfDimensions = 0, numberOfNeighbors = 0; |
||||
|
char *pointsFilename = NULL, *testFilename = NULL; |
||||
|
double seq_time = 0; |
||||
|
|
||||
|
/* Main */ |
||||
|
int main(int argc, char **argv){ |
||||
|
int numberOfTasks = 0, taskId = 0, chunksize = 0, myOffset = 0, destination = 0, source = 0; |
||||
|
double **myPoints, **inBuffer, **outBuffer, calcTimeSum = 0; |
||||
|
neighbor **sortedNeighborsArray; |
||||
|
MPI_Status statuses[2]; |
||||
|
MPI_Request requests[2]; |
||||
|
|
||||
|
getArguments(argc, argv); |
||||
|
|
||||
|
//Initializes mpi and necessary variables
|
||||
|
MPI_Init(&argc, &argv); |
||||
|
MPI_Comm_size(MPI_COMM_WORLD, &numberOfTasks); |
||||
|
if (numberOfPoints % numberOfTasks != 0){ |
||||
|
printf("Quitting. Number of points must be divisible by number of MPI tasks.\n"); |
||||
|
abExit(0); |
||||
|
} |
||||
|
MPI_Comm_rank(MPI_COMM_WORLD, &taskId); |
||||
|
|
||||
|
chunksize = numberOfPoints / numberOfTasks; //number of points each task has
|
||||
|
myOffset = taskId * chunksize; //this task's offset from (complete) point's array start
|
||||
|
destination = taskId + 1; //this task's destination task id for sending messages
|
||||
|
if (destination >= numberOfTasks){ |
||||
|
destination = 0; |
||||
|
} |
||||
|
source= taskId - 1; //this task's source task id for receiving messages
|
||||
|
if (source < 0){ |
||||
|
source = numberOfTasks - 1; |
||||
|
} |
||||
|
|
||||
|
init(&myPoints, &inBuffer, &outBuffer, &sortedNeighborsArray |
||||
|
,chunksize, myOffset * numberOfDimensions); |
||||
|
|
||||
|
MPI_Barrier(MPI_COMM_WORLD); |
||||
|
if (taskId == MASTER){ |
||||
|
gettimeofday(&startwtime, NULL); |
||||
|
} |
||||
|
|
||||
|
for (int chunk=-1; chunk<numberOfTasks-1; ++chunk){ |
||||
|
int lastLoop = (chunk == numberOfTasks-1-1) ? 1 : 0; |
||||
|
|
||||
|
if (!lastLoop){ //last loop doesn't send nor receive
|
||||
|
//sends-receives points array blocks
|
||||
|
MPI_Isend((chunk == -1) //if this is the first loop
|
||||
|
? &(myPoints[0][0]) //send this task's points
|
||||
|
: &(outBuffer[0][0]) //else send the points received from previous loop
|
||||
|
, chunksize * numberOfDimensions, MPI_DOUBLE, destination, taskId, MPI_COMM_WORLD |
||||
|
, &requests[BLOCK_SENT]); |
||||
|
MPI_Irecv(&(inBuffer[0][0]), chunksize * numberOfDimensions, MPI_DOUBLE, source, source |
||||
|
, MPI_COMM_WORLD, &requests[BLOCK_RECEIVED]); |
||||
|
} |
||||
|
|
||||
|
//offset of the task that sent new points block from (complete) point's array start
|
||||
|
//used for storing the correct neighbor id's in neighbors array
|
||||
|
int offset = source - chunk; |
||||
|
if (offset < 0){ |
||||
|
offset += numberOfTasks; |
||||
|
} |
||||
|
offset *= chunksize; |
||||
|
|
||||
|
gettimeofday(&calcStartWTime, NULL); |
||||
|
if (chunk == -1){ |
||||
|
//calculates distances between task's own points
|
||||
|
calculateDistances(&myPoints, &myPoints, &sortedNeighborsArray |
||||
|
, chunksize, myOffset, taskId * chunksize); |
||||
|
} else { |
||||
|
//calculates distances between task's points and new points received
|
||||
|
calculateDistances(&myPoints, &outBuffer, &sortedNeighborsArray |
||||
|
, chunksize, myOffset, offset); |
||||
|
} |
||||
|
gettimeofday(&calcEndWTime, NULL); |
||||
|
calcTimeSum += (double)((calcEndWTime.tv_usec - calcStartWTime.tv_usec)/1.0e6 |
||||
|
+ calcEndWTime.tv_sec - calcStartWTime.tv_sec); |
||||
|
|
||||
|
if (!lastLoop){ //last loop doesn't send nor receive
|
||||
|
//continues with next loop (and calculations) only after sending and receiving is done
|
||||
|
MPI_Waitall(2, requests, statuses); |
||||
|
} |
||||
|
|
||||
|
swapPointers(&inBuffer, &outBuffer); |
||||
|
} |
||||
|
|
||||
|
MPI_Barrier(MPI_COMM_WORLD); |
||||
|
if (taskId == MASTER){ |
||||
|
gettimeofday(&endwtime, NULL); |
||||
|
seq_time = (double)((endwtime.tv_usec - startwtime.tv_usec)/1.0e6 |
||||
|
+ endwtime.tv_sec - startwtime.tv_sec); |
||||
|
|
||||
|
printf("Wall clock time = %f\n\n", seq_time); |
||||
|
} |
||||
|
|
||||
|
if (test(&sortedNeighborsArray, chunksize, myOffset, testFilename)){ |
||||
|
printf("Validity check failed for task %d!\n", taskId); |
||||
|
} else { |
||||
|
printf("Validity check success for task %d!\n", taskId); |
||||
|
} |
||||
|
|
||||
|
if (taskId == MASTER){ |
||||
|
printf("Number of points = %d\n", numberOfPoints); |
||||
|
printf("Number of dimensions = %d\n", numberOfDimensions); |
||||
|
printf("Number of neighbors = %d\n", numberOfNeighbors); |
||||
|
printf("Number of tasks = %d\n", numberOfTasks); |
||||
|
} |
||||
|
for(int i=0; i<numberOfTasks; ++i) { |
||||
|
MPI_Barrier(MPI_COMM_WORLD); |
||||
|
if (i == taskId) { |
||||
|
printf("Task %d calculations time sum = %f\n", taskId, calcTimeSum); |
||||
|
/*
|
||||
|
Uncomment to print the results |
||||
|
*/ |
||||
|
/*for (int x=0; x<chunksize; ++x){
|
||||
|
for (int y=0; y<numberOfNeighbors; ++y){ |
||||
|
printf("%d to %d = %f\n", x + taskId * chunksize |
||||
|
, sortedNeighborsArray[x][y].neighborId, sortedNeighborsArray[x][y].distance); |
||||
|
} |
||||
|
printf("\n"); |
||||
|
}*/ |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
cleanUp(&myPoints, &inBuffer, &outBuffer, &sortedNeighborsArray, chunksize); |
||||
|
MPI_Finalize(); |
||||
|
} |
@ -0,0 +1,256 @@ |
|||||
|
#include <stdio.h> |
||||
|
#include <stdlib.h> |
||||
|
#include <sys/time.h> |
||||
|
|
||||
|
#include "knnMPINonBlockingDeclarations.h" |
||||
|
#include "mpi.h" |
||||
|
|
||||
|
void getArguments(int argc, char** argv){ |
||||
|
if (argc != 6) { |
||||
|
printf("Usage: %s p d k filename\nwhere:\n", argv[0]); |
||||
|
printf("\tp is the the number of points\n"); |
||||
|
printf("\td is the number of dimensions of each point\n"); |
||||
|
printf("\tk is the number of neighbors to search for\n"); |
||||
|
printf("\tdf is the filename of the dataset file\n"); |
||||
|
printf("\ttf is the filename of the dataset file\n"); |
||||
|
abExit(1); |
||||
|
} |
||||
|
numberOfPoints = atoi(argv[1]); |
||||
|
numberOfDimensions = atoi(argv[2]); |
||||
|
numberOfNeighbors = atoi(argv[3]); |
||||
|
if (numberOfNeighbors >= numberOfPoints) { |
||||
|
numberOfNeighbors = numberOfPoints - 1; |
||||
|
} |
||||
|
pointsFilename = argv[4]; |
||||
|
testFilename = argv[5]; |
||||
|
} |
||||
|
|
||||
|
void init(double ***pointsArray, double ***inBuffer, double ***outBuffer |
||||
|
, neighbor ***sortedNeighborsArray, int chunksize, int offset){ |
||||
|
//Allocates memory for points array
|
||||
|
*pointsArray = cMalloc(chunksize, numberOfDimensions); |
||||
|
//Allocates memory for the buffer storing points coming from another process
|
||||
|
*inBuffer = cMalloc(chunksize, numberOfDimensions); |
||||
|
//Allocates memory for the buffer storing points going out to another process
|
||||
|
*outBuffer = cMalloc(chunksize, numberOfDimensions); |
||||
|
|
||||
|
//Allocates memory for neighbors array
|
||||
|
if ( (*sortedNeighborsArray = (neighbor**)(malloc((sizeof(neighbor *)) * chunksize))) != NULL ){ |
||||
|
for (int row = 0; row < chunksize; ++row){ |
||||
|
if ( ( (*sortedNeighborsArray)[row] |
||||
|
= (neighbor*)(malloc((sizeof(neighbor)) * numberOfNeighbors)) ) == NULL ){ |
||||
|
printf("Error allocating memory\n"); |
||||
|
abExit(1); |
||||
|
} |
||||
|
} |
||||
|
} else { |
||||
|
printf("Error allocating memory\n"); |
||||
|
abExit(1); |
||||
|
} |
||||
|
|
||||
|
//Reads coordinates from the file
|
||||
|
if (readPointsArrayFromFile(pointsArray, chunksize, offset)){ |
||||
|
abExit(1); |
||||
|
} |
||||
|
|
||||
|
//Initializes neighbors array distances and ID's to -1
|
||||
|
for (int point=0; point<chunksize; ++point){ |
||||
|
for(int neighbor=0; neighbor<numberOfNeighbors; ++neighbor){ |
||||
|
(*sortedNeighborsArray)[point][neighbor].distance = -1; |
||||
|
(*sortedNeighborsArray)[point][neighbor].neighborId = -1; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
double **cMalloc(int rows, int columns){ |
||||
|
double **array; |
||||
|
//allocates a continuous block of memory
|
||||
|
double *tempArray = (double *)calloc(rows * columns, sizeof(double)); |
||||
|
if (tempArray == NULL){ |
||||
|
printf("Error allocating memory\n"); |
||||
|
abExit(1); |
||||
|
} |
||||
|
|
||||
|
//creates pointers to each row and column for easy indexing
|
||||
|
if ((array = ((double**)(malloc((sizeof(double *)) * rows)))) != NULL){ |
||||
|
for (int row = 0; row < rows; ++row){ |
||||
|
array[row] = &(tempArray[columns * row]); |
||||
|
} |
||||
|
} else { |
||||
|
printf("Error allocating memory\n"); |
||||
|
abExit(1); |
||||
|
} |
||||
|
|
||||
|
return array; |
||||
|
} |
||||
|
|
||||
|
int readPointsArrayFromFile(double ***array, int chunksize, int offset){ |
||||
|
FILE *pointsBinaryFile = fopen(pointsFilename, "rb"); |
||||
|
|
||||
|
if (pointsBinaryFile == NULL){ |
||||
|
printf("Couldn't open points file.\n"); |
||||
|
return 1; |
||||
|
} |
||||
|
if (fseek(pointsBinaryFile, offset * sizeof(double), SEEK_SET)){ |
||||
|
printf("Error reading the file. Quitting.\n"); |
||||
|
abExit(0); |
||||
|
} |
||||
|
for (int point=0; point<chunksize; ++point){ |
||||
|
if ( fread((*array)[point], sizeof(double), numberOfDimensions, pointsBinaryFile) |
||||
|
!= numberOfDimensions ){ |
||||
|
if(feof(pointsBinaryFile)){ |
||||
|
printf("Premature end of file reached.\n"); |
||||
|
} else{ |
||||
|
printf("Error reading points file."); |
||||
|
} |
||||
|
fclose(pointsBinaryFile); |
||||
|
return 1; |
||||
|
} |
||||
|
} |
||||
|
fclose(pointsBinaryFile); |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
void printArray(int rows, int columns, double ***array){ |
||||
|
for (int row=0; row<rows; ++row){ |
||||
|
for (int column=0; column<columns; ++column){ |
||||
|
printf("[%d][%d] = %f\n", row, column, (*array)[row][column]); |
||||
|
} |
||||
|
printf("\n"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void calculateDistances(double ***firstPointsSet, double ***secondPointsSet |
||||
|
, neighbor ***sortedNeighborsArray, int chunksize, int myOffset, int indexOffset){ |
||||
|
for (int firstPoint=0; firstPoint<chunksize; ++firstPoint){ |
||||
|
for (int secondPoint=0; secondPoint<chunksize; ++secondPoint){ |
||||
|
if (myOffset + firstPoint == indexOffset + secondPoint){ |
||||
|
continue; |
||||
|
} |
||||
|
double distance = 0; |
||||
|
for (int dimensionIndex=0; dimensionIndex<numberOfDimensions; ++dimensionIndex){ |
||||
|
double tmpDiff = (*firstPointsSet)[firstPoint][dimensionIndex] |
||||
|
- (*secondPointsSet)[secondPoint][dimensionIndex]; |
||||
|
distance += tmpDiff * tmpDiff; |
||||
|
} |
||||
|
addDistanceAndShift(sortedNeighborsArray, firstPoint, indexOffset + secondPoint |
||||
|
, distance); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void addDistanceAndShift(neighbor ***sortedNeighborsArray, int firstPointId, int secondPointId |
||||
|
, double pointsDistance){ |
||||
|
for (int arrayIndex=0; arrayIndex<numberOfNeighbors; ++arrayIndex){ |
||||
|
//Gets distance stored in the array for this index
|
||||
|
double thisNeighborDistance = (*sortedNeighborsArray)[firstPointId][arrayIndex].distance; |
||||
|
|
||||
|
if (thisNeighborDistance == -1){ //Loop reached the end of the array
|
||||
|
(*sortedNeighborsArray)[firstPointId][arrayIndex].distance = pointsDistance; |
||||
|
(*sortedNeighborsArray)[firstPointId][arrayIndex].neighborId = secondPointId; |
||||
|
break; |
||||
|
} else if (thisNeighborDistance > pointsDistance){ |
||||
|
//Distance at the this index is greater than the distance being inserted
|
||||
|
//Shifts right all non empty columns holding distances lower than pointsDistance
|
||||
|
for (int moveColumn=numberOfNeighbors-2; moveColumn>=arrayIndex; --moveColumn){ |
||||
|
double tempDistance = (*sortedNeighborsArray)[firstPointId][moveColumn].distance; |
||||
|
if (tempDistance == -1){ //Skips empty columns
|
||||
|
continue; |
||||
|
} |
||||
|
(*sortedNeighborsArray)[firstPointId][moveColumn+1].distance = tempDistance; |
||||
|
(*sortedNeighborsArray)[firstPointId][moveColumn+1].neighborId |
||||
|
= (*sortedNeighborsArray)[firstPointId][moveColumn].neighborId; |
||||
|
} |
||||
|
|
||||
|
/*
|
||||
|
Forward iteration is slower than reverse! |
||||
|
*/ |
||||
|
/*for (int moveColumn=arrayIndex; moveColumn<numberOfNeighbors-1; ++moveColumn){
|
||||
|
double tempDistance = (*sortedNeighborsArray)[firstPointId][moveColumn].distance; |
||||
|
if (tempDistance == -1){ //Skips empty columns
|
||||
|
break; |
||||
|
} |
||||
|
(*sortedNeighborsArray)[firstPointId][moveColumn+1].distance = tempDistance; |
||||
|
(*sortedNeighborsArray)[firstPointId][moveColumn+1].neighborId |
||||
|
= (*sortedNeighborsArray)[firstPointId][moveColumn].neighborId; |
||||
|
}*/ |
||||
|
|
||||
|
//Inserts pointsDistance in the space created after shifting
|
||||
|
(*sortedNeighborsArray)[firstPointId][arrayIndex].distance = pointsDistance; |
||||
|
(*sortedNeighborsArray)[firstPointId][arrayIndex].neighborId = secondPointId; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void swapPointers(double ***firstArray, double ***secondArray){ |
||||
|
double **tempPtr = *firstArray; |
||||
|
*firstArray = *secondArray; |
||||
|
*secondArray = tempPtr; |
||||
|
} |
||||
|
|
||||
|
int test(neighbor ***sortedNeighborsArray, int chunksize, int offset, char *testFilename){ |
||||
|
FILE *testFile = fopen(testFilename, "r"); |
||||
|
char *discarded = NULL; |
||||
|
size_t n = 0; |
||||
|
|
||||
|
if (testFile == NULL){ |
||||
|
printf("Couldn't open test file.\n"); |
||||
|
perror("fopen"); |
||||
|
return 1; |
||||
|
} |
||||
|
if (offset){ |
||||
|
for (int line=0; line<offset; ++line){ |
||||
|
if (getline(&discarded, &n, testFile) == -1){ |
||||
|
perror("Error reading test file"); |
||||
|
return 1; |
||||
|
} |
||||
|
n = 0; |
||||
|
} |
||||
|
free(discarded); |
||||
|
} |
||||
|
for (int point=0; point<chunksize; ++point){ |
||||
|
for (int i=0; i<numberOfNeighbors; ++i){ |
||||
|
int tempID = 0; |
||||
|
if (fscanf(testFile, "%d,", &tempID) == EOF){ |
||||
|
printf("Premature end of file reached.\n"); |
||||
|
fclose(testFile); |
||||
|
return 1; |
||||
|
} |
||||
|
if ((*sortedNeighborsArray)[point][i].neighborId != tempID - 1){ //-1 because f@ck matlab
|
||||
|
fclose(testFile); |
||||
|
return 1; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
fclose(testFile); |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
void cleanUp(double ***pointsArray, double ***inBuffer, double ***outBuffer |
||||
|
, neighbor ***sortedNeighborsArray, int chunksize){ |
||||
|
free((*pointsArray)[0]); |
||||
|
free(*pointsArray); |
||||
|
|
||||
|
free((*inBuffer)[0]); |
||||
|
free(*inBuffer); |
||||
|
|
||||
|
free((*outBuffer)[0]); |
||||
|
free(*outBuffer); |
||||
|
|
||||
|
for (int row=0; row<chunksize; ++row){ |
||||
|
free((*sortedNeighborsArray)[row]); |
||||
|
} |
||||
|
free(*sortedNeighborsArray); |
||||
|
} |
||||
|
|
||||
|
void abExit(int exitCode){ |
||||
|
int initialized = 0; |
||||
|
MPI_Initialized(&initialized); |
||||
|
if (initialized){ |
||||
|
MPI_Abort(MPI_COMM_WORLD, -1); |
||||
|
} |
||||
|
exit(0); |
||||
|
} |
@ -0,0 +1,91 @@ |
|||||
|
#ifndef KNNMPINONBLOCKINGFUNCTIONDECLARATIONS_H_ /* Include guard */ |
||||
|
#define KNNMPINONBLOCKINGFUNCTIONDECLARATIONS_H_ |
||||
|
|
||||
|
/* Constants definitions */ |
||||
|
#define MASTER 0 //task id of the master process
|
||||
|
#define BLOCK_SENT 0 //index of request used for sending blocks in the requests array
|
||||
|
#define BLOCK_RECEIVED 1 //index of request used for receiving blocks in the requests array
|
||||
|
|
||||
|
/* Structs */ |
||||
|
typedef struct neighbor{ //simple struct defining a point's neighbor
|
||||
|
double distance; //distance between the two neighbors (points)
|
||||
|
int neighborId; //index of the neighbor in the (complete) array of points
|
||||
|
} neighbor; |
||||
|
|
||||
|
/* Global variables */ |
||||
|
extern int numberOfPoints; //number of the points knn should run for
|
||||
|
extern int numberOfDimensions; //number of dimensions of each point
|
||||
|
extern int numberOfNeighbors; //number of nearest neighbors knn should find for each point
|
||||
|
extern char *pointsFilename; //name of the binary file storing the coordinates of points
|
||||
|
extern char *testFilename; //name of binary file storing correct neighbors IDs array
|
||||
|
|
||||
|
/* Functions declaration */ |
||||
|
|
||||
|
//Function getArguments is used to parse arguments provided to main
|
||||
|
void getArguments(int argc //arguments count
|
||||
|
, char** argv); //arguments array
|
||||
|
|
||||
|
//Function init allocates memory for the arrays used and initializes them
|
||||
|
void init(double ***pointsArray //pointer to the array of points
|
||||
|
, double ***inBuffer //pointer to the array used as input buffer for mpi
|
||||
|
, double ***outBuffer //pointer to the array used as output buffer for mpi
|
||||
|
, neighbor ***sortedNeighborsArray //pointer to the array holding the distances and ID's
|
||||
|
, int chunksize //number of rows (points) to be allocated
|
||||
|
, int offset); //process offset used when reading points from the file
|
||||
|
|
||||
|
//Function cMalloc allocates and returns a single block of continuous memory which can
|
||||
|
//be indexed like a regular array, e.g. array[row][column]
|
||||
|
double **cMalloc(int rows //number of rows to be allocated
|
||||
|
, int columns); //number of columns to be allocated
|
||||
|
|
||||
|
//Function readPointsArrayFromFile reads the coordinates of the points from a file and stores them
|
||||
|
//in an array
|
||||
|
int readPointsArrayFromFile(double ***array //array that will hold the coordinates of the points
|
||||
|
, int chunksize //number of rows (points) to be read
|
||||
|
, int offset); //offset from which reading will start
|
||||
|
|
||||
|
//Function printArray iterates the values of an array printing them
|
||||
|
void printArray(int rows //number of array's rows
|
||||
|
, int columns //number of array's columns
|
||||
|
, double ***array); //array to be printed
|
||||
|
|
||||
|
//Function calculateDistances calculates the distances between all points in two different sets and
|
||||
|
//adds the distance to sortedNeighborsArray
|
||||
|
void calculateDistances(double ***firstPointsSet //first pool of points coordinates
|
||||
|
, double ***secondPointsSet //second pool of points coordinates
|
||||
|
, neighbor ***sortedNeighborsArray //array that holds the distances
|
||||
|
, int chunksize //number of points
|
||||
|
, int myOffset //offset used for ID's of first pool's points
|
||||
|
, int indexOffset); //offset used for ID's of seconds pool's points
|
||||
|
|
||||
|
//Function addDistanceAndShift searches an array of neighbors (struct) for an index holding either
|
||||
|
//an empty distance or a distance that is greater than the one that came in the arguments
|
||||
|
//(pointsDistance), shifts "right" one time all values of the array after this index and fills the
|
||||
|
//empty position created after shifting with the one that came in the arguments (pointsDistance)
|
||||
|
void addDistanceAndShift(neighbor ***sortedNeighborsArray //array that holds the distances
|
||||
|
, int firstPointId //ID of the first point
|
||||
|
, int secondPointId //ID of the second point
|
||||
|
, double pointsDistance); //distance between the two points
|
||||
|
|
||||
|
//Function swapPointers swaps the memory blocks pointed to by two pointers
|
||||
|
void swapPointers(double ***firstArray //first memory block
|
||||
|
, double ***secondArray); //second memory block
|
||||
|
|
||||
|
//Function test checks the validity of the solution based on correct results previously generated
|
||||
|
//and stored in a text file
|
||||
|
int test(neighbor ***sortedNeighborsArray //array that holds the IDs
|
||||
|
, int chunksize //number of points
|
||||
|
, int offset //process offset
|
||||
|
, char *testFilename); //name of text file storing correct neighbors IDs array
|
||||
|
|
||||
|
//Function cleanUp frees all memory previously allocated
|
||||
|
void cleanUp(double ***pointsArray //points array pointer
|
||||
|
, double ***inBuffer //input buffer pointer
|
||||
|
, double ***outBuffer //output buffer pointer
|
||||
|
, neighbor ***sortedNeighborsArray //distances array pointer
|
||||
|
, int chunksize); //number of rows (points)
|
||||
|
|
||||
|
//Function abExit exits the program after checking for mpi initialization
|
||||
|
void abExit(int exitCode); //exit code to exit with
|
||||
|
|
||||
|
#endif // KNNMPINONBLOCKINGFUNCTIONDECLARATIONS_H_
|
Binary file not shown.
@ -0,0 +1,21 @@ |
|||||
|
TARGET=KnnMPINonBlockingTimeOptimized |
||||
|
CC=mpicc |
||||
|
CFLAGS=-Wall -O3 -std=gnu99 -I. |
||||
|
OBJ=knnMPINonBlocking.o knnMPINonBlockingDeclarations.o |
||||
|
DEPS=knnMPINonBlockingDeclarations.h |
||||
|
|
||||
|
.PHONY: default all clean |
||||
|
|
||||
|
default: $(TARGET) |
||||
|
all: default |
||||
|
|
||||
|
%.o: %.c $(DEPS) |
||||
|
$(CC) -c -o $@ $< $(CFLAGS) |
||||
|
|
||||
|
.PRECIOUS: $(TARGET) $(OBJ) |
||||
|
|
||||
|
$(TARGET): $(OBJ) |
||||
|
$(CC) -o $@ $^ $(CFLAGS) |
||||
|
|
||||
|
clean: |
||||
|
$(RM) *.o *~ |
@ -0,0 +1,149 @@ |
|||||
|
#include <stdio.h> |
||||
|
#include <stdlib.h> |
||||
|
#include <sys/time.h> |
||||
|
|
||||
|
#include "knnMPINonBlockingDeclarations.h" |
||||
|
#include "mpi.h" |
||||
|
|
||||
|
/* Structs */ |
||||
|
struct timeval startwtime, endwtime |
||||
|
, calcStartWTime, calcEndWTime; |
||||
|
|
||||
|
/* Global variables */ |
||||
|
int numberOfPoints = 0, numberOfDimensions = 0, numberOfNeighbors = 0, k = 0; |
||||
|
char *pointsFilename = NULL, *testFilename = NULL; |
||||
|
double seq_time = 0; |
||||
|
|
||||
|
/* Main */ |
||||
|
int main(int argc, char **argv){ |
||||
|
int numberOfTasks = 0, taskId = 0, chunksize = 0, myOffset = 0, destination = 0, source = 0; |
||||
|
double **myPoints, **inBuffer, **outBuffer, calcTimeSum = 0; |
||||
|
neighbor **sortedNeighborsArray; |
||||
|
MPI_Status statuses[2]; |
||||
|
MPI_Request requests[2]; |
||||
|
|
||||
|
getArguments(argc, argv); |
||||
|
|
||||
|
//Initializes mpi and necessary variables
|
||||
|
MPI_Init(&argc, &argv); |
||||
|
MPI_Comm_size(MPI_COMM_WORLD, &numberOfTasks); |
||||
|
if (numberOfPoints % numberOfTasks != 0){ |
||||
|
printf("Quitting. Number of points must be divisible by number of MPI tasks.\n"); |
||||
|
abExit(0); |
||||
|
} |
||||
|
MPI_Comm_rank(MPI_COMM_WORLD, &taskId); |
||||
|
|
||||
|
chunksize = numberOfPoints / numberOfTasks; //number of points each task has
|
||||
|
myOffset = taskId * chunksize; //this task's offset from (complete) point's array start
|
||||
|
destination = taskId + 1; //this task's destination task id for sending messages
|
||||
|
if (destination >= numberOfTasks){ |
||||
|
destination = 0; |
||||
|
} |
||||
|
source= taskId - 1; //this task's source task id for receiving messages
|
||||
|
if (source < 0){ |
||||
|
source = numberOfTasks - 1; |
||||
|
} |
||||
|
|
||||
|
init(&myPoints, &inBuffer, &outBuffer, &sortedNeighborsArray |
||||
|
,chunksize, myOffset * numberOfDimensions); |
||||
|
|
||||
|
MPI_Barrier(MPI_COMM_WORLD); |
||||
|
if (taskId == MASTER){ |
||||
|
gettimeofday(&startwtime, NULL); |
||||
|
} |
||||
|
|
||||
|
for (int chunk=-1; chunk<numberOfTasks-1; ++chunk){ |
||||
|
int lastLoop = (chunk == numberOfTasks-1-1) ? 1 : 0; |
||||
|
|
||||
|
if (!lastLoop){ //last loop doesn't send nor receive
|
||||
|
//sends-receives points array blocks
|
||||
|
MPI_Isend((chunk == -1) //if this is the first loop
|
||||
|
? &(myPoints[0][0]) //send this task's points
|
||||
|
: &(outBuffer[0][0]) //else send the points received from previous loop
|
||||
|
, chunksize * numberOfDimensions, MPI_DOUBLE, destination, taskId, MPI_COMM_WORLD |
||||
|
, &requests[BLOCK_SENT]); |
||||
|
MPI_Irecv(&(inBuffer[0][0]), chunksize * numberOfDimensions, MPI_DOUBLE, source, source |
||||
|
, MPI_COMM_WORLD, &requests[BLOCK_RECEIVED]); |
||||
|
} |
||||
|
|
||||
|
//offset of the task that sent new points block from (complete) point's array start
|
||||
|
//used for storing the correct neighbor id's in neighbors array
|
||||
|
int offset = source - chunk; |
||||
|
if (offset < 0){ |
||||
|
offset += numberOfTasks; |
||||
|
} |
||||
|
offset *= chunksize; |
||||
|
|
||||
|
gettimeofday(&calcStartWTime, NULL); |
||||
|
if (chunk == -1){ |
||||
|
//calculates distances between task's own points
|
||||
|
calculateDistances(&myPoints, &myPoints, &sortedNeighborsArray |
||||
|
, chunksize, myOffset, taskId * chunksize); |
||||
|
} else { |
||||
|
//calculates distances between task's points and new points received
|
||||
|
calculateDistances(&myPoints, &outBuffer, &sortedNeighborsArray |
||||
|
, chunksize, myOffset, offset); |
||||
|
} |
||||
|
gettimeofday(&calcEndWTime, NULL); |
||||
|
calcTimeSum += (double)((calcEndWTime.tv_usec - calcStartWTime.tv_usec)/1.0e6 |
||||
|
+ calcEndWTime.tv_sec - calcStartWTime.tv_sec); |
||||
|
|
||||
|
if (!lastLoop){ //last loop doesn't send nor receive
|
||||
|
//continues with next loop (and calculations) only after sending and receiving is done
|
||||
|
MPI_Waitall(2, requests, statuses); |
||||
|
} |
||||
|
|
||||
|
swapPointers(&inBuffer, &outBuffer); |
||||
|
} |
||||
|
|
||||
|
gettimeofday(&calcStartWTime, NULL); |
||||
|
|
||||
|
for (int point=0; point<chunksize; ++point){ |
||||
|
qsort (sortedNeighborsArray[point], numberOfNeighbors, sizeof(neighbor), compare); |
||||
|
} |
||||
|
|
||||
|
gettimeofday(&calcEndWTime, NULL); |
||||
|
calcTimeSum += (double)((calcEndWTime.tv_usec - calcStartWTime.tv_usec)/1.0e6 |
||||
|
+ calcEndWTime.tv_sec - calcStartWTime.tv_sec); |
||||
|
|
||||
|
MPI_Barrier(MPI_COMM_WORLD); |
||||
|
if (taskId == MASTER){ |
||||
|
gettimeofday(&endwtime, NULL); |
||||
|
seq_time = (double)((endwtime.tv_usec - startwtime.tv_usec)/1.0e6 |
||||
|
+ endwtime.tv_sec - startwtime.tv_sec); |
||||
|
|
||||
|
printf("Wall clock time = %f\n\n", seq_time); |
||||
|
} |
||||
|
|
||||
|
if (test(&sortedNeighborsArray, chunksize, myOffset, testFilename)){ |
||||
|
printf("Validity check failed for task %d!\n", taskId); |
||||
|
} else { |
||||
|
printf("Validity check success for task %d!\n", taskId); |
||||
|
} |
||||
|
|
||||
|
if (taskId == MASTER){ |
||||
|
printf("Number of points = %d\n", numberOfPoints); |
||||
|
printf("Number of dimensions = %d\n", numberOfDimensions); |
||||
|
printf("Number of neighbors = %d\n", numberOfNeighbors); |
||||
|
printf("Number of tasks = %d\n", numberOfTasks); |
||||
|
} |
||||
|
for(int i=0; i<numberOfTasks; ++i) { |
||||
|
MPI_Barrier(MPI_COMM_WORLD); |
||||
|
if (i == taskId) { |
||||
|
printf("Task %d calculations time sum = %f\n", taskId, calcTimeSum); |
||||
|
/*
|
||||
|
Uncomment to print the results |
||||
|
*/ |
||||
|
/*for (int x=0; x<chunksize; ++x){
|
||||
|
for (int y=0; y<k; ++y){ |
||||
|
printf("%d to %d = %f\n", x + taskId * chunksize |
||||
|
, sortedNeighborsArray[x][y].neighborId, sortedNeighborsArray[x][y].distance); |
||||
|
} |
||||
|
printf("\n"); |
||||
|
}*/ |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
cleanUp(&myPoints, &inBuffer, &outBuffer, &sortedNeighborsArray, chunksize); |
||||
|
MPI_Finalize(); |
||||
|
} |
Binary file not shown.
@ -0,0 +1,237 @@ |
|||||
|
#include <stdio.h> |
||||
|
#include <stdlib.h> |
||||
|
#include <float.h> |
||||
|
|
||||
|
#include "knnMPINonBlockingDeclarations.h" |
||||
|
#include "mpi.h" |
||||
|
|
||||
|
void getArguments(int argc, char** argv){ |
||||
|
if (argc != 6) { |
||||
|
printf("Usage: %s p d k filename\nwhere:\n", argv[0]); |
||||
|
printf("\tp is the the number of points\n"); |
||||
|
printf("\td is the number of dimensions of each point\n"); |
||||
|
printf("\tk is the number of neighbors to search for\n"); |
||||
|
printf("\tdf is the filename of the dataset file\n"); |
||||
|
printf("\ttf is the filename of the dataset file\n"); |
||||
|
abExit(1); |
||||
|
} |
||||
|
numberOfPoints = atoi(argv[1]); |
||||
|
numberOfDimensions = atoi(argv[2]); |
||||
|
numberOfNeighbors = numberOfPoints - 1; |
||||
|
k = atoi(argv[3]); |
||||
|
if (k >= numberOfPoints){ |
||||
|
k = numberOfPoints - 1; |
||||
|
} |
||||
|
pointsFilename = argv[4]; |
||||
|
testFilename = argv[5]; |
||||
|
} |
||||
|
|
||||
|
void init(double ***pointsArray, double ***inBuffer, double ***outBuffer |
||||
|
, neighbor ***sortedNeighborsArray, int chunksize, int offset){ |
||||
|
//Allocates memory for points array
|
||||
|
*pointsArray = cMalloc(chunksize, numberOfDimensions); |
||||
|
//Allocates memory for the buffer storing points coming from another process
|
||||
|
*inBuffer = cMalloc(chunksize, numberOfDimensions); |
||||
|
//Allocates memory for the buffer storing points going out to another process
|
||||
|
*outBuffer = cMalloc(chunksize, numberOfDimensions); |
||||
|
|
||||
|
//Allocates memory for neighbors array
|
||||
|
if ( (*sortedNeighborsArray = (neighbor**)(malloc((sizeof(neighbor *)) * chunksize))) != NULL ){ |
||||
|
for (int row = 0; row < chunksize; ++row){ |
||||
|
if ( ( (*sortedNeighborsArray)[row] |
||||
|
= (neighbor*)(malloc((sizeof(neighbor)) * numberOfNeighbors)) ) == NULL ){ |
||||
|
printf("Error allocating memory\n"); |
||||
|
abExit(1); |
||||
|
} |
||||
|
} |
||||
|
} else { |
||||
|
printf("Error allocating memory\n"); |
||||
|
abExit(1); |
||||
|
} |
||||
|
|
||||
|
//Reads coordinates from the file
|
||||
|
if (readPointsArrayFromFile(pointsArray, chunksize, offset)){ |
||||
|
abExit(1); |
||||
|
} |
||||
|
|
||||
|
//Initializes neighbors array distances and ID's to -1
|
||||
|
for (int point=0; point<chunksize; ++point){ |
||||
|
for(int neighbor=0; neighbor<numberOfNeighbors; ++neighbor){ |
||||
|
(*sortedNeighborsArray)[point][neighbor].distance = DBL_MAX; |
||||
|
(*sortedNeighborsArray)[point][neighbor].neighborId = -1; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
double **cMalloc(int rows, int columns){ |
||||
|
double **array; |
||||
|
//allocates a continuous block of memory
|
||||
|
double *tempArray = (double *)calloc(rows * columns, sizeof(double)); |
||||
|
if (tempArray == NULL){ |
||||
|
printf("Error allocating memory\n"); |
||||
|
abExit(1); |
||||
|
} |
||||
|
|
||||
|
//creates pointers to each row and column for easy indexing
|
||||
|
if ((array = ((double**)(malloc((sizeof(double *)) * rows)))) != NULL){ |
||||
|
for (int row = 0; row < rows; ++row){ |
||||
|
array[row] = &(tempArray[columns * row]); |
||||
|
} |
||||
|
} else { |
||||
|
printf("Error allocating memory\n"); |
||||
|
abExit(1); |
||||
|
} |
||||
|
|
||||
|
return array; |
||||
|
} |
||||
|
|
||||
|
int readPointsArrayFromFile(double ***array, int chunksize, int offset){ |
||||
|
FILE *pointsBinaryFile = fopen(pointsFilename, "rb"); |
||||
|
|
||||
|
if (pointsBinaryFile == NULL){ |
||||
|
printf("Couldn't open points file.\n"); |
||||
|
return 1; |
||||
|
} |
||||
|
if (fseek(pointsBinaryFile, offset * sizeof(double), SEEK_SET)){ |
||||
|
printf("Error reading the file. Quitting.\n"); |
||||
|
abExit(0); |
||||
|
} |
||||
|
for (int point=0; point<chunksize; ++point){ |
||||
|
if ( fread((*array)[point], sizeof(double), numberOfDimensions, pointsBinaryFile) |
||||
|
!= numberOfDimensions ){ |
||||
|
if(feof(pointsBinaryFile)){ |
||||
|
printf("Premature end of file reached.\n"); |
||||
|
} else{ |
||||
|
printf("Error reading points file."); |
||||
|
} |
||||
|
fclose(pointsBinaryFile); |
||||
|
return 1; |
||||
|
} |
||||
|
} |
||||
|
fclose(pointsBinaryFile); |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
void printArray(int rows, int columns, double ***array){ |
||||
|
for (int row=0; row<rows; ++row){ |
||||
|
for (int column=0; column<columns; ++column){ |
||||
|
printf("[%d][%d] = %f\n", row, column, (*array)[row][column]); |
||||
|
} |
||||
|
printf("\n"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void calculateDistances(double ***firstPointsSet, double ***secondPointsSet |
||||
|
, neighbor ***sortedNeighborsArray, int chunksize, int myOffset, int indexOffset){ |
||||
|
for (int firstPoint=0; firstPoint<chunksize; ++firstPoint){ |
||||
|
for (int secondPoint=0; secondPoint<chunksize; ++secondPoint){ |
||||
|
if (myOffset + firstPoint == indexOffset + secondPoint){ |
||||
|
continue; |
||||
|
} |
||||
|
double distance = 0; |
||||
|
for (int dimensionIndex=0; dimensionIndex<numberOfDimensions; ++dimensionIndex){ |
||||
|
double tmpDiff = (*firstPointsSet)[firstPoint][dimensionIndex] |
||||
|
- (*secondPointsSet)[secondPoint][dimensionIndex]; |
||||
|
distance += tmpDiff * tmpDiff; |
||||
|
} |
||||
|
addDistance(sortedNeighborsArray, firstPoint, myOffset + firstPoint |
||||
|
, indexOffset + secondPoint, distance); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void addDistance(neighbor ***sortedNeighborsArray, int firstPointIndex, int firstPointId |
||||
|
, int secondPointId, double pointsDistance){ |
||||
|
//Determines actual index in which the distance will be added
|
||||
|
int insertIndex = secondPointId; |
||||
|
if (secondPointId > firstPointId){ |
||||
|
--insertIndex; |
||||
|
} |
||||
|
|
||||
|
(*sortedNeighborsArray)[firstPointIndex][insertIndex].distance = pointsDistance; |
||||
|
(*sortedNeighborsArray)[firstPointIndex][insertIndex].neighborId = secondPointId; |
||||
|
} |
||||
|
|
||||
|
int compare (const void *a, const void *b){ |
||||
|
//Casts arguments to pointers to neighbors
|
||||
|
const neighbor *neighborA = (neighbor*) a; |
||||
|
const neighbor *neighborB = (neighbor*) b; |
||||
|
|
||||
|
if (neighborA->distance == neighborB->distance){ |
||||
|
return 0; |
||||
|
} else{ |
||||
|
return neighborA->distance > neighborB->distance ? 1 : -1; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void swapPointers(double ***firstArray, double ***secondArray){ |
||||
|
double **tempPtr = *firstArray; |
||||
|
*firstArray = *secondArray; |
||||
|
*secondArray = tempPtr; |
||||
|
} |
||||
|
|
||||
|
int test(neighbor ***sortedNeighborsArray, int chunksize, int offset, char *testFilename){ |
||||
|
FILE *testFile = fopen(testFilename, "r"); |
||||
|
char *discarded = NULL; |
||||
|
size_t n = 0; |
||||
|
|
||||
|
if (testFile == NULL){ |
||||
|
printf("Couldn't open test file.\n"); |
||||
|
perror("fopen"); |
||||
|
return 1; |
||||
|
} |
||||
|
if (offset){ |
||||
|
for (int line=0; line<offset; ++line){ |
||||
|
if (getline(&discarded, &n, testFile) == -1){ |
||||
|
perror("Error reading test file"); |
||||
|
return 1; |
||||
|
} |
||||
|
n = 0; |
||||
|
} |
||||
|
free(discarded); |
||||
|
} |
||||
|
for (int point=0; point<chunksize; ++point){ |
||||
|
for (int i=0; i<k; ++i){ |
||||
|
int tempID = 0; |
||||
|
if (fscanf(testFile, "%d,", &tempID) == EOF){ |
||||
|
printf("Premature end of file reached.\n"); |
||||
|
fclose(testFile); |
||||
|
return 1; |
||||
|
} |
||||
|
if ((*sortedNeighborsArray)[point][i].neighborId != tempID - 1){ //-1 because f@ck matlab
|
||||
|
fclose(testFile); |
||||
|
return 1; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
fclose(testFile); |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
void cleanUp(double ***pointsArray, double ***inBuffer, double ***outBuffer |
||||
|
, neighbor ***sortedNeighborsArray, int chunksize){ |
||||
|
free((*pointsArray)[0]); |
||||
|
free(*pointsArray); |
||||
|
|
||||
|
free((*inBuffer)[0]); |
||||
|
free(*inBuffer); |
||||
|
|
||||
|
free((*outBuffer)[0]); |
||||
|
free(*outBuffer); |
||||
|
|
||||
|
for (int row=0; row<chunksize; ++row){ |
||||
|
free((*sortedNeighborsArray)[row]); |
||||
|
} |
||||
|
free(*sortedNeighborsArray); |
||||
|
} |
||||
|
|
||||
|
void abExit(int exitCode){ |
||||
|
int initialized = 0; |
||||
|
MPI_Initialized(&initialized); |
||||
|
if (initialized){ |
||||
|
MPI_Abort(MPI_COMM_WORLD, -1); |
||||
|
} |
||||
|
exit(0); |
||||
|
} |
@ -0,0 +1,95 @@ |
|||||
|
#ifndef KNNMPINONBLOCKINGFUNCTIONDECLARATION_H_ /* Include guard */ |
||||
|
#define KNNMPINONBLOCKINGFUNCTIONDECLARATION_H_ |
||||
|
|
||||
|
/* Constants definitions */ |
||||
|
#define MASTER 0 //task id of the master process
|
||||
|
#define BLOCK_SENT 0 //index of request used for sending blocks in the requests array
|
||||
|
#define BLOCK_RECEIVED 1 //index of request used for receiving blocks in the requests array
|
||||
|
|
||||
|
/* Structs */ |
||||
|
typedef struct neighbor{ //simple struct defining a point's neighbor
|
||||
|
double distance; //distance between the two neighbors (points)
|
||||
|
int neighborId; //index of the neighbor in the (complete) array of points
|
||||
|
} neighbor; |
||||
|
|
||||
|
/* Global variables */ |
||||
|
extern int numberOfPoints; //number of the points knn should run for
|
||||
|
extern int numberOfDimensions; //number of dimensions of each point
|
||||
|
extern int numberOfNeighbors; //number of nearest neighbors that should be found for each point
|
||||
|
extern int k; //number of nearest neighbors requested by the user
|
||||
|
extern char *pointsFilename; //name of the binary file storing the coordinates of points
|
||||
|
extern char *testFilename; //name of binary file storing correct neighbors IDs array
|
||||
|
|
||||
|
/* Functions declaration */ |
||||
|
|
||||
|
//Function getArguments is used to parse arguments provided to main
|
||||
|
void getArguments(int argc //arguments count
|
||||
|
, char** argv); //arguments array
|
||||
|
|
||||
|
//Function init allocates memory for the arrays used and initializes them
|
||||
|
void init(double ***pointsArray //pointer to the array of points
|
||||
|
, double ***inBuffer //pointer to the array used as input buffer for mpi
|
||||
|
, double ***outBuffer //pointer to the array used as output buffer for mpi
|
||||
|
, neighbor ***sortedNeighborsArray //pointer to the array holding the distances and ID's
|
||||
|
, int chunksize //number of rows (points) to be allocated
|
||||
|
, int offset); //process offset used when reading points from the file
|
||||
|
|
||||
|
//Function cMalloc allocates and returns a single block of continuous memory which can
|
||||
|
//be indexed like a regular array, e.g. array[row][column]
|
||||
|
double **cMalloc(int rows //number of rows to be allocated
|
||||
|
, int columns); //number of columns to be allocated
|
||||
|
|
||||
|
//Function readPointsArrayFromFile reads the coordinates of the points from a file and stores them
|
||||
|
//in an array
|
||||
|
int readPointsArrayFromFile(double ***array //array that will hold the coordinates of the points
|
||||
|
, int chunksize //number of rows (points) to be read
|
||||
|
, int offset); //offset from which reading will start
|
||||
|
|
||||
|
//Function printArray iterates the values of an array printing them
|
||||
|
void printArray(int rows //number of array's rows
|
||||
|
, int columns //number of array's columns
|
||||
|
, double ***array); //array to be printed
|
||||
|
|
||||
|
//Function calculateDistances calculates the distances between all points in two different sets and
|
||||
|
//adds the distance to sortedNeighborsArray
|
||||
|
void calculateDistances(double ***firstPointsSet //first pool of points coordinates
|
||||
|
, double ***secondPointsSet //second pool of points coordinates
|
||||
|
, neighbor ***sortedNeighborsArray //array that holds the distances
|
||||
|
, int chunksize //number of points
|
||||
|
, int myOffset //offset used for ID's of first pool's points
|
||||
|
, int indexOffset); //offset used for ID's of seconds pool's points
|
||||
|
|
||||
|
//Function addDistance adds distances to sorted neighbors array sorted by the ID of the neighbor
|
||||
|
void addDistance(neighbor ***sortedNeighborsArray //array that holds the distances
|
||||
|
, int firstPointIndex //Index of the first point in task's array
|
||||
|
, int firstPointId //ID of the first point
|
||||
|
, int secondPointId //ID of the second point
|
||||
|
, double pointsDistance); //distance between the two points
|
||||
|
|
||||
|
//Function compare compares two neighbors using their distance fields, returns 0 if distances are
|
||||
|
//equal, 1 if distance of first argument is greater and -1 otherwise
|
||||
|
int compare (const void *a //first neighbor
|
||||
|
, const void *b); //second neighbor
|
||||
|
|
||||
|
//Function swapPointers swaps the memory blocks pointed to by two pointers
|
||||
|
void swapPointers(double ***firstArray //first memory block
|
||||
|
, double ***secondArray); //second memory block
|
||||
|
|
||||
|
//Function test checks the validity of the solution based on correct results previously generated
|
||||
|
//and stored in a text file
|
||||
|
int test(neighbor ***sortedNeighborsArray //array that holds the IDs
|
||||
|
, int chunksize //number of points
|
||||
|
, int offset //process offset
|
||||
|
, char *testFilename); //name of text file storing correct neighbors IDs array
|
||||
|
|
||||
|
//Function cleanUp frees all memory previously allocated
|
||||
|
void cleanUp(double ***pointsArray //points array pointer
|
||||
|
, double ***inBuffer //input buffer pointer
|
||||
|
, double ***outBuffer //output buffer pointer
|
||||
|
, neighbor ***sortedNeighborsArray //distanced array pointer
|
||||
|
, int chunksize); //number of rows (points)
|
||||
|
|
||||
|
//Function abExit exits the program after checking for mpi initialization
|
||||
|
void abExit(int exitCode); //exit code to exit with
|
||||
|
|
||||
|
#endif // KNNMPINONBLOCKINGFUNCTIONDECLARATION_H_
|
Binary file not shown.
@ -0,0 +1,22 @@ |
|||||
|
Project includes 6 versions of a knn algorithm implementation: |
||||
|
Serial - space optimized |
||||
|
Serial - time optimized |
||||
|
MPI parallel - blocking communications - space optimized |
||||
|
MPI parallel - blocking communications - time optimized |
||||
|
MPI parallel - non blocking communications - space optimized |
||||
|
MPI parallel - non blocking communications - time optimized |
||||
|
|
||||
|
Project folder also includes some test files and execution results (stats folder). |
||||
|
|
||||
|
In folder testFiles there is a dataset of 60000 points of 30 dimensions each, as |
||||
|
well as three IDX files extracted from Matlab storing correctly sorted IDs. |
||||
|
These files are named according to the convention: numberOfPoints_k |
||||
|
after the number of points and selected k that were used to run the Matlab |
||||
|
script. |
||||
|
|
||||
|
To run any version first run make. Then copy testFiles/data.bin and one of the |
||||
|
IDX test files into the folder. Finally run with: |
||||
|
mpiexec -np numTasks ./prog.out numPoints numDimensions k data.bin idxFileName |
||||
|
|
||||
|
To extract a new IDX file from Matlab run knn with the dataset and then extract |
||||
|
IDX variable to an ods/excel. Open the generated file and save as csv. |
@ -0,0 +1,21 @@ |
|||||
|
TARGET=KnnSerialSpaceOptimized |
||||
|
CC=gcc |
||||
|
CFLAGS=-Wall -O3 -std=gnu99 -I. |
||||
|
OBJ=knnSerial.o knnSerialDeclarations.o |
||||
|
DEPS=knnSerialDeclarations.h |
||||
|
|
||||
|
.PHONY: default all clean |
||||
|
|
||||
|
default: $(TARGET) |
||||
|
all: default |
||||
|
|
||||
|
%.o: %.c $(DEPS) |
||||
|
$(CC) -c -o $@ $< $(CFLAGS) |
||||
|
|
||||
|
.PRECIOUS: $(TARGET) $(OBJ) |
||||
|
|
||||
|
$(TARGET): $(OBJ) |
||||
|
$(CC) -o $@ $^ $(CFLAGS) |
||||
|
|
||||
|
clean: |
||||
|
$(RM) *.o *~ |
@ -0,0 +1,48 @@ |
|||||
|
#include <stdio.h> |
||||
|
#include <sys/time.h> |
||||
|
|
||||
|
#include "knnSerialDeclarations.h" |
||||
|
|
||||
|
/* Structs */ |
||||
|
struct timeval startwtime, endwtime; |
||||
|
double seq_time; |
||||
|
|
||||
|
/* Global variable */ |
||||
|
int numberOfPoints = 0, numberOfDimensions = 0, numberOfNeighbors = 0, direction = 0; |
||||
|
char *pointsFilename, *testFilename; |
||||
|
|
||||
|
/* Main */ |
||||
|
int main(int argc, char **argv){ |
||||
|
double **pointsArray; |
||||
|
neighbor **sortedNeighborsArray; |
||||
|
|
||||
|
getArguments(argc, argv); |
||||
|
init(&pointsArray, &sortedNeighborsArray); |
||||
|
|
||||
|
gettimeofday(&startwtime, NULL); |
||||
|
|
||||
|
calculateDistances(&pointsArray, &pointsArray, &sortedNeighborsArray); |
||||
|
|
||||
|
gettimeofday(&endwtime, NULL); |
||||
|
seq_time = (double)((endwtime.tv_usec - startwtime.tv_usec)/1.0e6 |
||||
|
+ endwtime.tv_sec - startwtime.tv_sec); |
||||
|
printf("Wall clock time = %f\n\n", seq_time); |
||||
|
|
||||
|
if (test(&sortedNeighborsArray, testFilename)){ |
||||
|
printf("Validity check failed!\n"); |
||||
|
} else { |
||||
|
printf("Validity check success!\n"); |
||||
|
} |
||||
|
|
||||
|
/*
|
||||
|
Uncomment to print the results |
||||
|
*/ |
||||
|
/*for (int x=0; x<numberOfPoints; ++x){
|
||||
|
for (int y=0; y<numberOfNeighbors; ++y){ |
||||
|
printf("%d to %d = %f\n", x, sortedNeighborsArray[x][y].neighborId, sortedNeighborsArray[x][y].distance); |
||||
|
} |
||||
|
printf("\n"); |
||||
|
}*/ |
||||
|
|
||||
|
cleanUp(&pointsArray, &sortedNeighborsArray); |
||||
|
} |
@ -0,0 +1,192 @@ |
|||||
|
#include <stdio.h> |
||||
|
#include <stdlib.h> |
||||
|
#include <math.h> |
||||
|
|
||||
|
#include "knnSerialDeclarations.h" |
||||
|
|
||||
|
void getArguments(int argc, char** argv){ |
||||
|
if (argc != 6) { |
||||
|
printf("Usage: %s p d k filename tfilename\nwhere:\n", argv[0]); |
||||
|
printf("\tp is the the number of points\n"); |
||||
|
printf("\td is the number of dimensions of each point\n"); |
||||
|
printf("\tk is the number of neighbors to search for\n"); |
||||
|
printf("\tfilename is the filename of the dataset file\n"); |
||||
|
printf("\tfilename is the filename of the test file\n"); |
||||
|
exit(1); |
||||
|
} |
||||
|
numberOfPoints = atoi(argv[1]); |
||||
|
numberOfDimensions = atoi(argv[2]); |
||||
|
numberOfNeighbors = atoi(argv[3]); |
||||
|
if (numberOfNeighbors >= numberOfPoints) { |
||||
|
numberOfNeighbors = numberOfPoints - 1; |
||||
|
} |
||||
|
pointsFilename = argv[4]; |
||||
|
testFilename = argv[5]; |
||||
|
} |
||||
|
|
||||
|
void init(double ***pointsArray, neighbor ***sortedNeighborsArray){ |
||||
|
//Allocates continuous memory for points array
|
||||
|
*pointsArray = cMalloc(numberOfPoints, numberOfDimensions); |
||||
|
|
||||
|
//Allocates memory for neighbors array
|
||||
|
if ( (*sortedNeighborsArray = (neighbor**)(malloc((sizeof(neighbor *)) * numberOfPoints)) ) |
||||
|
!= NULL){ |
||||
|
for (int row = 0; row < numberOfPoints; ++row){ |
||||
|
if ( ((*sortedNeighborsArray)[row] |
||||
|
= (neighbor*)(malloc((sizeof(neighbor)) * numberOfNeighbors)) ) == NULL){ |
||||
|
printf("Error allocating memory\n"); |
||||
|
exit(1); |
||||
|
} |
||||
|
} |
||||
|
} else { |
||||
|
printf("Error allocating memory\n"); |
||||
|
exit(1); |
||||
|
} |
||||
|
|
||||
|
//Reads coordinates from the file
|
||||
|
if (readPointsArrayFromFile(pointsArray)){ |
||||
|
printf("Press any key to exit.\n"); |
||||
|
getchar(); |
||||
|
exit(1); |
||||
|
} |
||||
|
|
||||
|
//Initializes neighbors array distances and ID's to -1
|
||||
|
for (int point=0; point<numberOfPoints; ++point){ |
||||
|
for(int neighbor=0; neighbor<numberOfNeighbors; ++neighbor){ |
||||
|
(*sortedNeighborsArray)[point][neighbor].distance = -1; |
||||
|
(*sortedNeighborsArray)[point][neighbor].neighborId = -1; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
double **cMalloc(int rows, int columns){ |
||||
|
double *tempArray = (double *)malloc(rows * columns * sizeof(double)); |
||||
|
double **array; |
||||
|
|
||||
|
if ((array = ((double**)(malloc((sizeof(double *)) * rows)))) != NULL){ |
||||
|
for (int row = 0; row < rows; ++row){ |
||||
|
array[row] = &(tempArray[columns * row]); |
||||
|
} |
||||
|
} else { |
||||
|
printf("Error allocating memory\n"); |
||||
|
exit(1); |
||||
|
} |
||||
|
|
||||
|
return array; |
||||
|
} |
||||
|
|
||||
|
int readPointsArrayFromFile(double ***array){ |
||||
|
FILE *pointsBinaryFile = fopen(pointsFilename, "rb"); |
||||
|
|
||||
|
if (pointsBinaryFile == NULL){ |
||||
|
printf("Couldn't open points file.\n"); |
||||
|
return 1; |
||||
|
} |
||||
|
for (int point=0; point<numberOfPoints; ++point){ |
||||
|
if (fread((*array)[point], sizeof(double), numberOfDimensions, pointsBinaryFile) |
||||
|
!= numberOfDimensions) { |
||||
|
if(feof(pointsBinaryFile)){ |
||||
|
printf("Premature end of file reached.\n"); |
||||
|
} else{ |
||||
|
printf("Error reading points file."); |
||||
|
} |
||||
|
fclose(pointsBinaryFile); |
||||
|
return 1; |
||||
|
} |
||||
|
} |
||||
|
fclose(pointsBinaryFile); |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
void printArray(int rows, int columns, double ***array){ |
||||
|
for (int row=0; row<rows; ++row){ |
||||
|
for (int column=0; column<columns; ++column){ |
||||
|
printf("[%d][%d] = %f\n", row, column, (*array)[row][column]); |
||||
|
} |
||||
|
printf("\n"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void calculateDistances(double ***firstPointsSet, double ***secondPointsSet |
||||
|
, neighbor ***sortedNeighborsArray){ |
||||
|
for (int firstPoint=0; firstPoint<numberOfPoints; ++firstPoint){ |
||||
|
for (int secondPoint=0; secondPoint<numberOfPoints; ++secondPoint){ |
||||
|
if (firstPoint == secondPoint){ |
||||
|
continue; |
||||
|
} |
||||
|
double distance = 0; |
||||
|
for (int dimensionIndex=0; dimensionIndex<numberOfDimensions; ++dimensionIndex){ |
||||
|
distance += pow((*firstPointsSet)[firstPoint][dimensionIndex] |
||||
|
- (*secondPointsSet)[secondPoint][dimensionIndex] ,2); |
||||
|
} |
||||
|
addDistanceAndShift(sortedNeighborsArray, firstPoint, secondPoint, distance); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void addDistanceAndShift(neighbor ***sortedNeighborsArray, int firstPointId, int secondPointId |
||||
|
, double pointsDistance){ |
||||
|
for (int arrayIndex=0; arrayIndex<numberOfNeighbors; ++arrayIndex){ |
||||
|
//Gets distance stored in the array for this index
|
||||
|
double thisNeighborDistance = (*sortedNeighborsArray)[firstPointId][arrayIndex].distance; |
||||
|
|
||||
|
if (thisNeighborDistance == -1){ //Loop reached the end of the array
|
||||
|
(*sortedNeighborsArray)[firstPointId][arrayIndex].distance = pointsDistance; |
||||
|
(*sortedNeighborsArray)[firstPointId][arrayIndex].neighborId = secondPointId; |
||||
|
break; |
||||
|
} else if (thisNeighborDistance > pointsDistance){ |
||||
|
//Shifts right all non empty columns holding distances lower than pointsDistance
|
||||
|
for (int moveColumn=numberOfNeighbors-2; moveColumn>=arrayIndex; --moveColumn){ |
||||
|
double tempDistance = (*sortedNeighborsArray)[firstPointId][moveColumn].distance; |
||||
|
if (tempDistance == -1){ //Skips empty columns
|
||||
|
continue; |
||||
|
} |
||||
|
(*sortedNeighborsArray)[firstPointId][moveColumn+1].distance = tempDistance; |
||||
|
(*sortedNeighborsArray)[firstPointId][moveColumn+1].neighborId |
||||
|
= (*sortedNeighborsArray)[firstPointId][moveColumn].neighborId; |
||||
|
} |
||||
|
//Inserts pointsDistance in the space created after shifting
|
||||
|
(*sortedNeighborsArray)[firstPointId][arrayIndex].distance = pointsDistance; |
||||
|
(*sortedNeighborsArray)[firstPointId][arrayIndex].neighborId = secondPointId; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
int test(neighbor ***sortedNeighborsArray, char *testFilename){ |
||||
|
FILE *testFile = fopen(testFilename, "r"); |
||||
|
|
||||
|
if (testFile == NULL){ |
||||
|
printf("Couldn't open test file.\n"); |
||||
|
perror("fopen"); |
||||
|
return 1; |
||||
|
} |
||||
|
for (int point=0; point<numberOfPoints; ++point){ |
||||
|
for (int i=0; i<numberOfNeighbors; ++i){ |
||||
|
int tempID = 0; |
||||
|
if (fscanf(testFile, "%d,", &tempID) == EOF){ |
||||
|
printf("Premature end of file reached.\n"); |
||||
|
fclose(testFile); |
||||
|
return 1; |
||||
|
} |
||||
|
if ((*sortedNeighborsArray)[point][i].neighborId != tempID - 1){ |
||||
|
fclose(testFile); |
||||
|
return 1; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
fclose(testFile); |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
void cleanUp(double ***pointsArray, neighbor ***sortedNeighborsArray){ |
||||
|
free((*pointsArray)[0]); |
||||
|
free(*pointsArray); |
||||
|
|
||||
|
for (int row=0; row<numberOfPoints; ++row){ |
||||
|
free((*sortedNeighborsArray)[row]); |
||||
|
} |
||||
|
free(*sortedNeighborsArray); |
||||
|
} |
@ -0,0 +1,65 @@ |
|||||
|
#ifndef KNNSERIALDECLARATIONS_H_ /* Include guard */ |
||||
|
#define KNNSERIALDECLARATIONS_H_ |
||||
|
|
||||
|
/* Structs */ |
||||
|
typedef struct neighbor{ //simple struct defining a point's neighbor
|
||||
|
double distance; //distance between the two neighbors (points)
|
||||
|
int neighborId; //index of the neighbor in the (complete) array of points
|
||||
|
} neighbor; |
||||
|
|
||||
|
/* Global variables */ |
||||
|
extern int numberOfPoints; //number of the points knn should run for
|
||||
|
extern int numberOfDimensions; //number of dimensions of each point
|
||||
|
extern int numberOfNeighbors; //number of nearest neighbors knn should find for each point
|
||||
|
extern char *pointsFilename; //name of the binary file storing the coordinates of points
|
||||
|
extern char *testFilename; //name of binary file storing correct neighbors IDs array
|
||||
|
|
||||
|
/* Functions declaration */ |
||||
|
|
||||
|
//Function getArguments is used to parse arguments provided to main
|
||||
|
void getArguments(int argc //arguments count
|
||||
|
, char** argv); //arguments array
|
||||
|
|
||||
|
//Function init allocates memory for the arrays used and initializes them
|
||||
|
void init(double ***pointsArray //pointer to the array of points
|
||||
|
, neighbor ***sortedNeighborsArray); //pointer to the array holding the distances and ID's
|
||||
|
|
||||
|
//Function cMalloc allocates and returns a single block of continuous memory which can
|
||||
|
//be indexed like a regular array, e.g. array[row][column]
|
||||
|
double **cMalloc(int rows //number of rows to be allocated
|
||||
|
, int columns); //number of columns to be allocated
|
||||
|
|
||||
|
//Function readPointsArrayFromFile reads the coordinates of the points from a file and stores them
|
||||
|
//in an array
|
||||
|
int readPointsArrayFromFile(double ***array); //array that will hold the coordinates of the points
|
||||
|
|
||||
|
//Function printArray iterates the values of an array printing them
|
||||
|
void printArray(int rows //number of array's rows
|
||||
|
, int columns //number of array's columns
|
||||
|
, double ***array); //array to be printed
|
||||
|
|
||||
|
//Function calculateDistances calculates the distances between all points in two different sets and
|
||||
|
//adds the distance to sortedNeighborsArray
|
||||
|
void calculateDistances(double ***firstPointsSet //first pool of points coordinates
|
||||
|
, double ***secondPointsSet //second pool of points coordinates
|
||||
|
, neighbor ***sortedNeighborsArray); //array that holds the distances
|
||||
|
|
||||
|
//Function addDistanceAndShift searches an array of neighbors (struct) for an index holding either
|
||||
|
//an empty distance or a distance that is greater than the one that came in the arguments
|
||||
|
//(pointsDistance), shifts "right" one time all values of the array after this index and fills the
|
||||
|
//empty position created after shifting with the one that came in the arguments (pointsDistance)
|
||||
|
void addDistanceAndShift(neighbor ***sortedNeighborsArray //array that holds the distances
|
||||
|
, int firstPointId //ID of the first point
|
||||
|
, int secondPointId //ID of the second point
|
||||
|
, double pointsDistance); //distance between the two points
|
||||
|
|
||||
|
//Function test checks the validity of the solution based on correct results previously generated
|
||||
|
//and stored in a text file
|
||||
|
int test(neighbor ***sortedNeighborsArray //array that holds the IDs
|
||||
|
, char *testFilename); //name of text file storing correct neighbors IDs array
|
||||
|
|
||||
|
//Function cleanUp frees all memory previously allocated
|
||||
|
void cleanUp(double ***pointsArray //points array pointer
|
||||
|
, neighbor ***sortedNeighborsArray); //distances array pointer
|
||||
|
|
||||
|
#endif // KNNMPINONBLOCKINGFUNCTIONDECLARATIONS_H_
|
@ -0,0 +1,21 @@ |
|||||
|
TARGET=KnnSerialTimeOptimized |
||||
|
CC=gcc |
||||
|
CFLAGS=-Wall -O3 -std=gnu99 -I. |
||||
|
OBJ=knnSerial.o knnSerialDeclarations.o |
||||
|
DEPS=knnSerialDeclarations.h |
||||
|
|
||||
|
.PHONY: default all clean |
||||
|
|
||||
|
default: $(TARGET) |
||||
|
all: default |
||||
|
|
||||
|
%.o: %.c $(DEPS) |
||||
|
$(CC) -c -o $@ $< $(CFLAGS) |
||||
|
|
||||
|
.PRECIOUS: $(TARGET) $(OBJ) |
||||
|
|
||||
|
$(TARGET): $(OBJ) |
||||
|
$(CC) -o $@ $^ $(CFLAGS) |
||||
|
|
||||
|
clean: |
||||
|
$(RM) *.o *~ |
@ -0,0 +1,53 @@ |
|||||
|
#include <stdio.h> |
||||
|
#include <stdlib.h> |
||||
|
#include <sys/time.h> |
||||
|
|
||||
|
#include "knnSerialDeclarations.h" |
||||
|
|
||||
|
/* Structs */ |
||||
|
struct timeval startwtime, endwtime; |
||||
|
double seq_time; |
||||
|
|
||||
|
/* Global variable */ |
||||
|
int numberOfPoints = 0, numberOfDimensions = 0, numberOfNeighbors = 0, direction = 0, k = 0; |
||||
|
char *pointsFilename, *testFilename; |
||||
|
|
||||
|
/* Main */ |
||||
|
int main(int argc, char **argv){ |
||||
|
double **pointsArray; |
||||
|
neighbor **sortedNeighborsArray; |
||||
|
|
||||
|
getArguments(argc, argv); |
||||
|
init(&pointsArray, &sortedNeighborsArray); |
||||
|
|
||||
|
gettimeofday(&startwtime, NULL); |
||||
|
|
||||
|
calculateDistances(&pointsArray, &pointsArray, &sortedNeighborsArray); |
||||
|
|
||||
|
for (int point=0; point<numberOfPoints; ++point){ |
||||
|
qsort (sortedNeighborsArray[point], numberOfNeighbors, sizeof(neighbor), compare); |
||||
|
} |
||||
|
|
||||
|
gettimeofday(&endwtime, NULL); |
||||
|
seq_time = (double)((endwtime.tv_usec - startwtime.tv_usec)/1.0e6 |
||||
|
+ endwtime.tv_sec - startwtime.tv_sec); |
||||
|
printf("Wall clock time = %f\n\n", seq_time); |
||||
|
|
||||
|
if (test(&sortedNeighborsArray, testFilename)){ |
||||
|
printf("Validity check failed!\n"); |
||||
|
} else { |
||||
|
printf("Validity check success!\n"); |
||||
|
} |
||||
|
|
||||
|
/*
|
||||
|
Uncomment to print the results |
||||
|
*/ |
||||
|
/*for (int x=0; x<numberOfPoints; ++x){
|
||||
|
for (int y=0; y<k; ++y){ |
||||
|
printf("%d to %d = %f\n", x, sortedNeighborsArray[x][y].neighborId, sortedNeighborsArray[x][y].distance); |
||||
|
} |
||||
|
printf("\n"); |
||||
|
}*/ |
||||
|
|
||||
|
cleanUp(&pointsArray, &sortedNeighborsArray); |
||||
|
} |
@ -0,0 +1,188 @@ |
|||||
|
#include <stdio.h> |
||||
|
#include <stdlib.h> |
||||
|
#include <math.h> |
||||
|
|
||||
|
#include "knnSerialDeclarations.h" |
||||
|
|
||||
|
void getArguments(int argc, char** argv){ |
||||
|
if (argc != 6) { |
||||
|
printf("Usage: %s p d k filename tfilename\nwhere:\n", argv[0]); |
||||
|
printf("\tp is the the number of points\n"); |
||||
|
printf("\td is the number of dimensions of each point\n"); |
||||
|
printf("\tk is the number of neighbors to search for\n"); |
||||
|
printf("\tfilename is the filename of the dataset file\n"); |
||||
|
printf("\tfilename is the filename of the test file\n"); |
||||
|
exit(1); |
||||
|
} |
||||
|
numberOfPoints = atoi(argv[1]); |
||||
|
numberOfDimensions = atoi(argv[2]); |
||||
|
numberOfNeighbors = numberOfPoints - 1; |
||||
|
k = atoi(argv[3]); |
||||
|
if (k >= numberOfPoints){ |
||||
|
k = numberOfPoints - 1; |
||||
|
} |
||||
|
pointsFilename = argv[4]; |
||||
|
testFilename = argv[5]; |
||||
|
} |
||||
|
|
||||
|
void init(double ***pointsArray, neighbor ***sortedNeighborsArray){ |
||||
|
//Allocates continuous memory for points array
|
||||
|
*pointsArray = cMalloc(numberOfPoints, numberOfDimensions); |
||||
|
|
||||
|
//Allocates memory for neighbors array
|
||||
|
if ( (*sortedNeighborsArray = (neighbor**)(malloc((sizeof(neighbor *)) * numberOfPoints)) ) |
||||
|
!= NULL){ |
||||
|
for (int row = 0; row < numberOfPoints; ++row){ |
||||
|
if ( ((*sortedNeighborsArray)[row] |
||||
|
= (neighbor*)(malloc((sizeof(neighbor)) * numberOfNeighbors)) ) == NULL){ |
||||
|
printf("Error allocating memory\n"); |
||||
|
exit(1); |
||||
|
} |
||||
|
} |
||||
|
} else { |
||||
|
printf("Error allocating memory\n"); |
||||
|
exit(1); |
||||
|
} |
||||
|
|
||||
|
//Reads coordinates from the file
|
||||
|
if (readPointsArrayFromFile(pointsArray)){ |
||||
|
printf("Press any key to exit.\n"); |
||||
|
getchar(); |
||||
|
exit(1); |
||||
|
} |
||||
|
|
||||
|
//Initializes neighbors array distances and ID's to -1
|
||||
|
for (int point=0; point<numberOfPoints; ++point){ |
||||
|
for(int neighbor=0; neighbor<numberOfNeighbors; ++neighbor){ |
||||
|
(*sortedNeighborsArray)[point][neighbor].distance = -1; |
||||
|
(*sortedNeighborsArray)[point][neighbor].neighborId = -1; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
double **cMalloc(int rows, int columns){ |
||||
|
double *tempArray = (double *)malloc(rows * columns * sizeof(double)); |
||||
|
double **array; |
||||
|
|
||||
|
if ((array = ((double**)(malloc((sizeof(double *)) * rows)))) != NULL){ |
||||
|
for (int row = 0; row < rows; ++row){ |
||||
|
array[row] = &(tempArray[columns * row]); |
||||
|
} |
||||
|
} else { |
||||
|
printf("Error allocating memory\n"); |
||||
|
exit(1); |
||||
|
} |
||||
|
|
||||
|
return array; |
||||
|
} |
||||
|
|
||||
|
int readPointsArrayFromFile(double ***array){ |
||||
|
FILE *pointsBinaryFile = fopen(pointsFilename, "rb"); |
||||
|
|
||||
|
if (pointsBinaryFile == NULL){ |
||||
|
printf("Couldn't open points file.\n"); |
||||
|
return 1; |
||||
|
} |
||||
|
for (int point=0; point<numberOfPoints; ++point){ |
||||
|
if (fread((*array)[point], sizeof(double), numberOfDimensions, pointsBinaryFile) |
||||
|
!= numberOfDimensions) { |
||||
|
if(feof(pointsBinaryFile)){ |
||||
|
printf("Premature end of file reached.\n"); |
||||
|
} else{ |
||||
|
printf("Error reading points file."); |
||||
|
} |
||||
|
fclose(pointsBinaryFile); |
||||
|
return 1; |
||||
|
} |
||||
|
} |
||||
|
fclose(pointsBinaryFile); |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
void printArray(int rows, int columns, double ***array){ |
||||
|
for (int row=0; row<rows; ++row){ |
||||
|
for (int column=0; column<columns; ++column){ |
||||
|
printf("[%d][%d] = %f\n", row, column, (*array)[row][column]); |
||||
|
} |
||||
|
printf("\n"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void calculateDistances(double ***firstPointsSet, double ***secondPointsSet |
||||
|
, neighbor ***sortedNeighborsArray){ |
||||
|
for (int firstPoint=0; firstPoint<numberOfPoints; ++firstPoint){ |
||||
|
for (int secondPoint=0; secondPoint<numberOfPoints; ++secondPoint){ |
||||
|
if (firstPoint == secondPoint){ |
||||
|
continue; |
||||
|
} |
||||
|
double distance = 0; |
||||
|
for (int dimensionIndex=0; dimensionIndex<numberOfDimensions; ++dimensionIndex){ |
||||
|
distance += pow((*firstPointsSet)[firstPoint][dimensionIndex] |
||||
|
- (*secondPointsSet)[secondPoint][dimensionIndex] ,2); |
||||
|
} |
||||
|
addDistance(sortedNeighborsArray, firstPoint, secondPoint, distance); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void addDistance(neighbor ***sortedNeighborsArray, int firstPointId, int secondPointId |
||||
|
, double pointsDistance){ |
||||
|
//Determines actual index in which the distance will be added
|
||||
|
int insertIndex = secondPointId; |
||||
|
if (secondPointId > firstPointId){ |
||||
|
--insertIndex; |
||||
|
} |
||||
|
|
||||
|
(*sortedNeighborsArray)[firstPointId][insertIndex].distance = pointsDistance; |
||||
|
(*sortedNeighborsArray)[firstPointId][insertIndex].neighborId = secondPointId; |
||||
|
} |
||||
|
|
||||
|
int compare (const void *a, const void *b){ |
||||
|
//Casts arguments to pointers to neighbors
|
||||
|
const neighbor *neighborA = (neighbor*) a; |
||||
|
const neighbor *neighborB = (neighbor*) b; |
||||
|
|
||||
|
if (neighborA->distance == neighborB->distance){ |
||||
|
return 0; |
||||
|
} else{ |
||||
|
return neighborA->distance > neighborB->distance ? 1 : -1; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
int test(neighbor ***sortedNeighborsArray, char *testFilename){ |
||||
|
FILE *testFile = fopen(testFilename, "r"); |
||||
|
|
||||
|
if (testFile == NULL){ |
||||
|
printf("Couldn't open test file.\n"); |
||||
|
perror("fopen"); |
||||
|
return 1; |
||||
|
} |
||||
|
for (int point=0; point<numberOfPoints; ++point){ |
||||
|
for (int i=0; i<k; ++i){ |
||||
|
int tempID = 0; |
||||
|
if (fscanf(testFile, "%d,", &tempID) == EOF){ |
||||
|
printf("Premature end of file reached.\n"); |
||||
|
fclose(testFile); |
||||
|
return 1; |
||||
|
} |
||||
|
if ((*sortedNeighborsArray)[point][i].neighborId != tempID - 1){ |
||||
|
fclose(testFile); |
||||
|
return 1; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
fclose(testFile); |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
void cleanUp(double ***pointsArray, neighbor ***sortedNeighborsArray){ |
||||
|
free((*pointsArray)[0]); |
||||
|
free(*pointsArray); |
||||
|
|
||||
|
for (int row=0; row<numberOfPoints; ++row){ |
||||
|
free((*sortedNeighborsArray)[row]); |
||||
|
} |
||||
|
free(*sortedNeighborsArray); |
||||
|
} |
@ -0,0 +1,68 @@ |
|||||
|
#ifndef KNNSERIALDECLARATIONS_H_ /* Include guard */ |
||||
|
#define KNNSERIALDECLARATIONS_H_ |
||||
|
|
||||
|
/* Structs */ |
||||
|
typedef struct neighbor{ //simple struct defining a point's neighbor
|
||||
|
double distance; //distance between the two neighbors (points)
|
||||
|
int neighborId; //index of the neighbor in the (complete) array of points
|
||||
|
} neighbor; |
||||
|
|
||||
|
/* Global variables */ |
||||
|
extern int numberOfPoints; //number of the points knn should run for
|
||||
|
extern int numberOfDimensions; //number of dimensions of each point
|
||||
|
extern int numberOfNeighbors; //number of nearest neighbors knn should find for each point
|
||||
|
extern int k; //number of nearest neighbors requested by the user
|
||||
|
extern char *pointsFilename; //name of the binary file storing the coordinates of points
|
||||
|
extern char *testFilename; //name of binary file storing correct neighbors IDs array
|
||||
|
|
||||
|
/* Functions declaration */ |
||||
|
|
||||
|
//Function getArguments is used to parse arguments provided to main
|
||||
|
void getArguments(int argc //arguments count
|
||||
|
, char** argv); //arguments array
|
||||
|
|
||||
|
//Function init allocates memory for the arrays used and initializes them
|
||||
|
void init(double ***pointsArray //pointer to the array of points
|
||||
|
, neighbor ***sortedNeighborsArray); //pointer to the array holding the distances and ID's
|
||||
|
|
||||
|
//Function cMalloc allocates and returns a single block of continuous memory which can
|
||||
|
//be indexed like a regular array, e.g. array[row][column]
|
||||
|
double **cMalloc(int rows //number of rows to be allocated
|
||||
|
, int columns); //number of columns to be allocated
|
||||
|
|
||||
|
//Function readPointsArrayFromFile reads the coordinates of the points from a file and stores them
|
||||
|
//in an array
|
||||
|
int readPointsArrayFromFile(double ***array); //array that will hold the coordinates of the points
|
||||
|
|
||||
|
//Function printArray iterates the values of an array printing them
|
||||
|
void printArray(int rows //number of array's rows
|
||||
|
, int columns //number of array's columns
|
||||
|
, double ***array); //array to be printed
|
||||
|
|
||||
|
//Function calculateDistances calculates the distances between all points in two different sets and
|
||||
|
//adds the distance to sortedNeighborsArray
|
||||
|
void calculateDistances(double ***firstPointsSet //first pool of points coordinates
|
||||
|
, double ***secondPointsSet //second pool of points coordinates
|
||||
|
, neighbor ***sortedNeighborsArray); //array that holds the distances
|
||||
|
|
||||
|
//Function addDistance adds distances to sorted neighbors array, sorted by the ID of the neighbor
|
||||
|
void addDistance(neighbor ***sortedNeighborsArray //array that holds the distances
|
||||
|
, int firstPointId //ID of the first point
|
||||
|
, int secondPointId //ID of the second point
|
||||
|
, double pointsDistance); //distance between the two points
|
||||
|
|
||||
|
//Function compare compares two neighbors using their distance fields, returns 0 if distances are
|
||||
|
//equal, 1 if distance of first argument is greater and -1 otherwise
|
||||
|
int compare (const void *a //first neighbor
|
||||
|
, const void *b); //second neighbor
|
||||
|
|
||||
|
//Function test checks the validity of the solution based on correct results previously generated
|
||||
|
//and stored in a text file
|
||||
|
int test(neighbor ***sortedNeighborsArray //array that holds the IDs
|
||||
|
, char *testFilename); //name of text file storing correct neighbors IDs array
|
||||
|
|
||||
|
//Function cleanUp frees all memory previously allocated
|
||||
|
void cleanUp(double ***pointsArray //points array pointer
|
||||
|
, neighbor ***sortedNeighborsArray); //distances array pointer
|
||||
|
|
||||
|
#endif // KNNMPINONBLOCKINGFUNCTIONDECLARATIONS_H_
|
@ -0,0 +1,85 @@ |
|||||
|
#include <stdio.h> |
||||
|
#include <stdlib.h> |
||||
|
#include <math.h> |
||||
|
|
||||
|
void writeTotxt(int rows, int columns, double array[rows][columns], char *filename, |
||||
|
int commaSeperated, int tabSeperated); |
||||
|
|
||||
|
int main(int argc, char const *argv[]){ |
||||
|
double **pointsArray; |
||||
|
char binaryFilename[200], textFilename[200]; |
||||
|
int commaSeperated = 0, tabSeperated = 0; |
||||
|
int seperationMethod, numberOfRows, numberOfColumns; |
||||
|
|
||||
|
printf("Seperate values with:\n\t[0] Space (default)\n\t[1] Comma\n\t[2] Tab\nInput = "); |
||||
|
scanf("%d", &seperationMethod); |
||||
|
switch(seperationMethod){ |
||||
|
case 1 : |
||||
|
commaSeperated = 1; |
||||
|
break; |
||||
|
|
||||
|
case 2 : |
||||
|
tabSeperated = 1; |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
printf("\nArray rows = "); |
||||
|
scanf("%d", &numberOfRows); |
||||
|
printf("\nArray columns = "); |
||||
|
scanf("%d", &numberOfColumns); |
||||
|
|
||||
|
pointsArray = (double **)(malloc(numberOfRows * sizeof(double *))); |
||||
|
for (int i = 0; i < numberOfRows; ++i){ |
||||
|
pointsArray[i] = (double *)(malloc(numberOfColumns * sizeof(double))); |
||||
|
} |
||||
|
|
||||
|
printf("\nBinary filename = "); |
||||
|
scanf("%s", binaryFilename); |
||||
|
printf("\nText filename = "); |
||||
|
scanf("%s", textFilename); |
||||
|
|
||||
|
FILE *pointsBinaryFile; |
||||
|
pointsBinaryFile = fopen(binaryFilename,"rb"); |
||||
|
|
||||
|
if(fread(&pointsArray, sizeof(double), numberOfRows * numberOfColumns, |
||||
|
pointsBinaryFile) != numberOfRows * numberOfColumns) { |
||||
|
if(feof(pointsBinaryFile)) |
||||
|
printf("There were usefull info after the end of file.\n"); |
||||
|
else |
||||
|
printf("File read error.\n"); |
||||
|
return 1; |
||||
|
} |
||||
|
fclose(pointsBinaryFile); |
||||
|
|
||||
|
for (int i = 0; i < numberOfRows; ++i){ |
||||
|
for (int j = 0; j < numberOfColumns; ++j){ |
||||
|
printf("%f\n", pointsArray[i][j]); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
FILE *file = fopen(textFilename, "w"); |
||||
|
if (file == NULL){ |
||||
|
printf("Error opening file!\n"); |
||||
|
exit(1); |
||||
|
} |
||||
|
|
||||
|
for (int i = 0; i < numberOfRows; ++i){ |
||||
|
for (int j = 0; j < numberOfColumns; ++j){ |
||||
|
fprintf(file, "%f", pointsArray[i][j]); |
||||
|
if (j != numberOfColumns - 1){ |
||||
|
if (commaSeperated){ |
||||
|
fprintf(file, ", "); |
||||
|
} else if (tabSeperated){ |
||||
|
fprintf(file, "\t"); |
||||
|
} else { |
||||
|
fprintf(file, " "); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
fprintf(file, "\n"); |
||||
|
} |
||||
|
fclose(file); |
||||
|
|
||||
|
printf("Done! Press any key to exit.\n"); |
||||
|
getchar(); |
||||
|
} |
@ -0,0 +1,40 @@ |
|||||
|
#include <stdio.h> |
||||
|
#include <stdlib.h> |
||||
|
|
||||
|
#define NUMBER_OF_ROWS 3 |
||||
|
#define NUMBER_OF_COLUMNS 2 |
||||
|
|
||||
|
|
||||
|
int main(int argc, char const *argv[]){ |
||||
|
double pointsArray[NUMBER_OF_ROWS][NUMBER_OF_COLUMNS]; |
||||
|
int row, column; |
||||
|
|
||||
|
/*for (row=0; row<NUMBER_OF_ROWS; ++row){
|
||||
|
for (column=0; column<NUMBER_OF_COLUMNS; ++column){ |
||||
|
pointsArray[row][column] = rand() * 12.8; |
||||
|
printf("pointsArray[%d][%d] = %f\n", row, column, pointsArray[row][column]); |
||||
|
} |
||||
|
}*/ |
||||
|
pointsArray[0][0] = 0.0; |
||||
|
pointsArray[0][1] = 1.0; |
||||
|
|
||||
|
pointsArray[1][0] = 0.0; |
||||
|
pointsArray[1][1] = 2.0; |
||||
|
|
||||
|
pointsArray[2][0] = 0.0; |
||||
|
pointsArray[2][1] = 3.0; |
||||
|
|
||||
|
for (row=0; row<NUMBER_OF_ROWS; ++row){ |
||||
|
for (column=0; column<NUMBER_OF_COLUMNS; ++column){ |
||||
|
printf("pointsArray[%d][%d] = %f\n", row, column, pointsArray[row][column]); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
FILE *pointsBinaryFile; |
||||
|
pointsBinaryFile = fopen("points.bin","wb"); |
||||
|
fwrite(pointsArray, sizeof(double), NUMBER_OF_ROWS * NUMBER_OF_COLUMNS, pointsBinaryFile); |
||||
|
fclose(pointsBinaryFile); |
||||
|
|
||||
|
printf("Done!"); |
||||
|
scanf("%d", &row); |
||||
|
} |
@ -0,0 +1,198 @@ |
|||||
|
#include <stdio.h> |
||||
|
#include <stdlib.h> |
||||
|
#include <math.h> |
||||
|
|
||||
|
#define DEBUG 0 |
||||
|
|
||||
|
typedef struct neighbor{ |
||||
|
double distance; |
||||
|
int neighborId; |
||||
|
} neighbor; |
||||
|
|
||||
|
void getArgs(int argc, char** argv); |
||||
|
void init(double ***pointsArray, neighbor ***sortedNeighborsArray); |
||||
|
int readPointsArrayFromFile(double ***array); |
||||
|
void printArray(int rows, int columns, double ***array); |
||||
|
void addDistanceAndShift(neighbor ***sortedNeighborsArray, int firstPointId, int secondPointId, double pointsDistance); |
||||
|
void cleanUp(double ***pointsArray, neighbor ***sortedNeighborsArray); |
||||
|
|
||||
|
int numberOfPoints, numberOfDimensions, numberOfNeighbors; |
||||
|
|
||||
|
int main(int argc, char **argv){ |
||||
|
double **pointsArray; |
||||
|
neighbor **sortedNeighborsArray; |
||||
|
|
||||
|
getArgs(argc, argv); |
||||
|
init(&pointsArray, &sortedNeighborsArray); |
||||
|
//printArray(numberOfPoints, numberOfDimensions, &pointsArray);
|
||||
|
//printf("HERE\n");
|
||||
|
for (int firstPoint=0; firstPoint<numberOfPoints; ++firstPoint){ |
||||
|
for (int secondPoint=0; secondPoint<numberOfPoints; ++secondPoint){ |
||||
|
if (firstPoint == secondPoint){ |
||||
|
continue; |
||||
|
} |
||||
|
double distance = 0; |
||||
|
for (int dimensionIndex=0; dimensionIndex<numberOfDimensions; ++dimensionIndex){ |
||||
|
double diff = pointsArray[firstPoint][dimensionIndex] - pointsArray[secondPoint][dimensionIndex]; |
||||
|
distance += pow(diff ,2); |
||||
|
} |
||||
|
addDistanceAndShift(&sortedNeighborsArray, firstPoint, secondPoint, distance); |
||||
|
} |
||||
|
} |
||||
|
printf("HERE\n"); |
||||
|
|
||||
|
for (int x=0; x<numberOfPoints; ++x){ |
||||
|
for (int y=0; y<numberOfNeighbors; ++y){ |
||||
|
printf("%d to %d = %f\n", x, sortedNeighborsArray[x][y].neighborId, sortedNeighborsArray[x][y].distance); |
||||
|
} |
||||
|
printf("\n"); |
||||
|
} |
||||
|
|
||||
|
cleanUp(&pointsArray, &sortedNeighborsArray); |
||||
|
printf("Done! Press any key to exit.\n"); |
||||
|
getchar(); |
||||
|
} |
||||
|
|
||||
|
void getArgs(int argc, char** argv){ |
||||
|
/*if (argc != 4) {
|
||||
|
printf("Usage: %s p d k\nwhere:\n\tp is the the number of points\n\td is the number of dimensions of each point\n", |
||||
|
argv[0]); |
||||
|
printf("\tk is the number of neighbors to search for\n"); |
||||
|
exit(1); |
||||
|
}*/ |
||||
|
/*numberOfPoints = atoi(argv[1]);
|
||||
|
numberOfDimensions = atoi(argv[2]); |
||||
|
numberOfNeighbors = atoi(argv[3]); |
||||
|
if (numberOfNeighbors >= numberOfPoints) { |
||||
|
numberOfNeighbors = numberOfPoints - 1; |
||||
|
}*/ |
||||
|
numberOfPoints = 10; |
||||
|
numberOfDimensions = 10; |
||||
|
numberOfNeighbors = 5; |
||||
|
} |
||||
|
|
||||
|
void init(double ***pointsArray, neighbor ***sortedNeighborsArray){ |
||||
|
//Allocates memory for points array
|
||||
|
if ((*pointsArray = malloc((sizeof(double *)) * numberOfPoints)) != NULL){ |
||||
|
for (int row = 0; row < numberOfPoints; ++row){ |
||||
|
if (((*pointsArray)[row] = malloc((sizeof(double)) * numberOfDimensions)) == NULL){ |
||||
|
if (DEBUG){ |
||||
|
printf("Error allocating memory\n"); |
||||
|
} |
||||
|
exit(1); |
||||
|
} |
||||
|
} |
||||
|
} else { |
||||
|
if (DEBUG){ |
||||
|
printf("Error allocating memory\n"); |
||||
|
} |
||||
|
exit(1); |
||||
|
} |
||||
|
|
||||
|
//Allocates memory for neighbors array
|
||||
|
if ((*sortedNeighborsArray = malloc((sizeof(neighbor *)) * numberOfPoints)) != NULL){ |
||||
|
for (int row = 0; row < numberOfPoints; ++row){ |
||||
|
if (((*sortedNeighborsArray)[row] = malloc((sizeof(neighbor)) * numberOfNeighbors)) == NULL){ |
||||
|
if (DEBUG){ |
||||
|
printf("Error allocating memory\n"); |
||||
|
} |
||||
|
exit(1); |
||||
|
} |
||||
|
} |
||||
|
} else { |
||||
|
if (DEBUG){ |
||||
|
printf("Error allocating memory\n"); |
||||
|
} |
||||
|
exit(1); |
||||
|
} |
||||
|
|
||||
|
//Reads coordinates for the file
|
||||
|
if (readPointsArrayFromFile(pointsArray)){ |
||||
|
if (DEBUG){ |
||||
|
printf("Press any key to exit.\n"); |
||||
|
getchar(); |
||||
|
} |
||||
|
exit(1); |
||||
|
} |
||||
|
|
||||
|
//Initializes neighbors array distances to -1
|
||||
|
for (int row=0; row<numberOfPoints; ++row){ |
||||
|
for(int column=0; column<numberOfNeighbors; ++column){ |
||||
|
(*sortedNeighborsArray)[row][column].distance = -1; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
int readPointsArrayFromFile(double ***array){ |
||||
|
FILE *pointsBinaryFile; |
||||
|
pointsBinaryFile = fopen("data.bin","rb"); |
||||
|
|
||||
|
for (int point=0; point<numberOfPoints; ++point){ |
||||
|
if (fread((*array)[point], sizeof(double), numberOfDimensions, pointsBinaryFile) != numberOfDimensions) { |
||||
|
if(feof(pointsBinaryFile)){ |
||||
|
printf("There were info after the end of file.\n"); |
||||
|
} else{ |
||||
|
printf("Error reading points file."); |
||||
|
} |
||||
|
return 1; |
||||
|
} |
||||
|
} |
||||
|
fclose(pointsBinaryFile); |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
void printArray(int rows, int columns, double ***array){ |
||||
|
for (int row=0; row<rows; ++row){ |
||||
|
for (int column=0; column<columns; ++column){ |
||||
|
printf("[%d][%d] = %f\n", row, column, (*array)[row][column]); |
||||
|
} |
||||
|
printf("\n"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
void addDistanceAndShift(neighbor ***sortedNeighborsArray, int firstPointId, int secondPointId, double pointsDistance){ |
||||
|
if (DEBUG){ |
||||
|
printf("Got %d and %d = %f\n", firstPointId, secondPointId, pointsDistance); |
||||
|
} |
||||
|
|
||||
|
for (int arrayIndex=0; arrayIndex<numberOfNeighbors; ++arrayIndex){ |
||||
|
//Gets distance stored in the array for this index
|
||||
|
double thisNeighborDistance = (*sortedNeighborsArray)[firstPointId][arrayIndex].distance; |
||||
|
|
||||
|
if (thisNeighborDistance == -1){ //Loop reached the end of the array
|
||||
|
(*sortedNeighborsArray)[firstPointId][arrayIndex].distance = pointsDistance; |
||||
|
(*sortedNeighborsArray)[firstPointId][arrayIndex].neighborId = secondPointId; |
||||
|
break; |
||||
|
} else if (thisNeighborDistance > pointsDistance){ //Distance at the this index is greater than the distance being inserted
|
||||
|
//Shifts right all non empty columns holding distances lower than pointsDistance
|
||||
|
for (int moveColumn=numberOfNeighbors-2; moveColumn>=arrayIndex; --moveColumn){ |
||||
|
double tempDistance = (*sortedNeighborsArray)[firstPointId][moveColumn].distance; |
||||
|
if (tempDistance == -1){ //Skips empty columns
|
||||
|
continue; |
||||
|
} |
||||
|
(*sortedNeighborsArray)[firstPointId][moveColumn+1].distance = tempDistance; |
||||
|
(*sortedNeighborsArray)[firstPointId][moveColumn+1].neighborId = (*sortedNeighborsArray)[firstPointId][moveColumn].neighborId; |
||||
|
} |
||||
|
//Inserts pointsDistance in the space created after shifting
|
||||
|
(*sortedNeighborsArray)[firstPointId][arrayIndex].distance = pointsDistance; |
||||
|
(*sortedNeighborsArray)[firstPointId][arrayIndex].neighborId = secondPointId; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void cleanUp(double ***pointsArray, neighbor ***sortedNeighborsArray){ |
||||
|
for (int row=0; row<numberOfPoints; ++row){ |
||||
|
free((*pointsArray)[row]); |
||||
|
} |
||||
|
free(*pointsArray); |
||||
|
|
||||
|
//Crashes for some reason...
|
||||
|
/*for (int row=0; row<numberOfNeighbors; ++row){
|
||||
|
printf("%f\n", (*sortedNeighborsArray)[row][0]); |
||||
|
free((*sortedNeighborsArray)[row]); |
||||
|
}*/ |
||||
|
//free(*sortedNeighborsArray);
|
||||
|
} |
@ -0,0 +1,65 @@ |
|||||
|
#include <stdio.h> |
||||
|
#include <stdlib.h> |
||||
|
#include <math.h> |
||||
|
|
||||
|
#define NUMBER_OF_ROWS 10 |
||||
|
#define NUMBER_OF_COLUMNS 10 |
||||
|
|
||||
|
int readArrayFromFile(int rows, int columns, double array[rows][columns]); |
||||
|
void printPointsArray(int rows, int columns, double array[rows][columns]); |
||||
|
void init(int pointsArrayRows, int pointsArrayColumns, double pointsArray[pointsArrayRows][pointsArrayColumns]); |
||||
|
|
||||
|
int main(int argc, char const *argv[]){ |
||||
|
double **pointsArray; |
||||
|
int row; |
||||
|
|
||||
|
pointsArray = (double **)(malloc(NUMBER_OF_ROWS * sizeof(double *))); |
||||
|
for (int i = 0; i < NUMBER_OF_ROWS; ++i){ |
||||
|
pointsArray[i] = (double *)(malloc(NUMBER_OF_COLUMNS * sizeof(double))); |
||||
|
} |
||||
|
|
||||
|
init(NUMBER_OF_ROWS, NUMBER_OF_COLUMNS, &pointsArray); |
||||
|
printPointsArray(NUMBER_OF_ROWS, NUMBER_OF_COLUMNS, &pointsArray); |
||||
|
|
||||
|
printf("Done! Press any key to exit.\n"); |
||||
|
scanf("%d", &row); |
||||
|
} |
||||
|
|
||||
|
int readArrayFromFile(int rows, int columns, double array[rows][columns]){ |
||||
|
FILE *pointsBinaryFile; |
||||
|
pointsBinaryFile = fopen("data.bin","rb"); |
||||
|
|
||||
|
if(fread(array, sizeof(double), rows * columns, pointsBinaryFile) != rows * columns) { |
||||
|
if(feof(pointsBinaryFile)) |
||||
|
printf("There were usefull info after the end of file.\n"); |
||||
|
else |
||||
|
printf("File read error.\n"); |
||||
|
return 1; |
||||
|
} |
||||
|
fclose(pointsBinaryFile); |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
void printPointsArray(int rows, int columns, double array[rows][columns]){ |
||||
|
int row, column; |
||||
|
|
||||
|
for (row=0; row<rows; ++row){ |
||||
|
for (column=0; column<columns; ++column){ |
||||
|
printf("pointsArray[%d][%d] = %f\n", row, column, array[row][column]); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void init(int pointsArrayRows, int pointsArrayColumns, double pointsArray[pointsArrayRows][pointsArrayColumns]){ |
||||
|
int row, column; |
||||
|
|
||||
|
if (readArrayFromFile(pointsArrayRows, pointsArrayColumns, pointsArray)){ |
||||
|
printf("Failed... Press any key to exit.\n"); |
||||
|
scanf("%d", &row); |
||||
|
exit(1); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
@ -0,0 +1,60 @@ |
|||||
|
#include <stdio.h> |
||||
|
#include <stdlib.h> |
||||
|
#include <math.h> |
||||
|
|
||||
|
#define NUMBER_OF_ROWS 10 |
||||
|
#define NUMBER_OF_COLUMNS 10 |
||||
|
|
||||
|
int readArrayFromFile(int rows, int columns, double array[rows][columns]); |
||||
|
void printPointsArray(int rows, int columns, double array[rows][columns]); |
||||
|
void init(int pointsArrayRows, int pointsArrayColumns, double pointsArray[pointsArrayRows][pointsArrayColumns]); |
||||
|
|
||||
|
int main(int argc, char const *argv[]){ |
||||
|
double pointsArray[NUMBER_OF_ROWS][NUMBER_OF_COLUMNS]; |
||||
|
int row; |
||||
|
|
||||
|
init(NUMBER_OF_ROWS, NUMBER_OF_COLUMNS, pointsArray); |
||||
|
printPointsArray(NUMBER_OF_ROWS, NUMBER_OF_COLUMNS, pointsArray); |
||||
|
|
||||
|
printf("Done! Press any key to exit.\n"); |
||||
|
scanf("%d", &row); |
||||
|
} |
||||
|
|
||||
|
int readArrayFromFile(int rows, int columns, double array[rows][columns]){ |
||||
|
FILE *pointsBinaryFile; |
||||
|
pointsBinaryFile = fopen("data.bin","rb"); |
||||
|
|
||||
|
if(fread(array, sizeof(double), rows * columns, pointsBinaryFile) != rows * columns) { |
||||
|
if(feof(pointsBinaryFile)) |
||||
|
printf("There were usefull info after the end of file.\n"); |
||||
|
else |
||||
|
printf("File read error.\n"); |
||||
|
return 1; |
||||
|
} |
||||
|
fclose(pointsBinaryFile); |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
void printPointsArray(int rows, int columns, double array[rows][columns]){ |
||||
|
int row, column; |
||||
|
|
||||
|
for (row=0; row<rows; ++row){ |
||||
|
for (column=0; column<columns; ++column){ |
||||
|
printf("pointsArray[%d][%d] = %f\n", row, column, array[row][column]); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void init(int pointsArrayRows, int pointsArrayColumns, double pointsArray[pointsArrayRows][pointsArrayColumns]){ |
||||
|
int row, column; |
||||
|
|
||||
|
if (readArrayFromFile(pointsArrayRows, pointsArrayColumns, pointsArray)){ |
||||
|
printf("Failed... Press any key to exit.\n"); |
||||
|
scanf("%d", &row); |
||||
|
exit(1); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 0.034069 |
||||
|
|
||||
|
Number of points = 1000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 communications time sum = 0.000285 |
||||
|
Task 0 calculations time sum = 0.033611 |
||||
|
Task 1 communications time sum = 0.000269 |
||||
|
Task 1 calculations time sum = 0.033482 |
||||
|
Task 2 communications time sum = 0.000286 |
||||
|
Task 2 calculations time sum = 0.033540 |
||||
|
Task 3 communications time sum = 0.000304 |
||||
|
Task 3 calculations time sum = 0.033434 |
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 7.261491 |
||||
|
|
||||
|
Number of points = 13000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 12999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 communications time sum = 0.002371 |
||||
|
Task 0 calculations time sum = 7.258963 |
||||
|
Task 1 communications time sum = 0.003553 |
||||
|
Task 1 calculations time sum = 7.226678 |
||||
|
Task 2 communications time sum = 0.003680 |
||||
|
Task 2 calculations time sum = 7.163300 |
||||
|
Task 3 communications time sum = 0.003646 |
||||
|
Task 3 calculations time sum = 7.179779 |
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 12.719311 |
||||
|
|
||||
|
Number of points = 17000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 16999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 communications time sum = 0.009364 |
||||
|
Task 0 calculations time sum = 12.709771 |
||||
|
Task 1 communications time sum = 0.013145 |
||||
|
Task 1 calculations time sum = 12.654160 |
||||
|
Task 2 communications time sum = 0.012834 |
||||
|
Task 2 calculations time sum = 12.640520 |
||||
|
Task 3 communications time sum = 0.007404 |
||||
|
Task 3 calculations time sum = 12.674974 |
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 19.688050 |
||||
|
|
||||
|
Number of points = 21000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 20999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 communications time sum = 0.006936 |
||||
|
Task 0 calculations time sum = 19.658426 |
||||
|
Task 1 communications time sum = 0.002660 |
||||
|
Task 1 calculations time sum = 19.588951 |
||||
|
Task 2 communications time sum = 0.002747 |
||||
|
Task 2 calculations time sum = 19.654984 |
||||
|
Task 3 communications time sum = 0.005355 |
||||
|
Task 3 calculations time sum = 19.682092 |
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 0.994548 |
||||
|
|
||||
|
Number of points = 5000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 4999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 communications time sum = 0.002459 |
||||
|
Task 0 calculations time sum = 0.990055 |
||||
|
Task 1 communications time sum = 0.000776 |
||||
|
Task 1 calculations time sum = 0.990929 |
||||
|
Task 2 communications time sum = 0.002396 |
||||
|
Task 3 communications time sum = 0.002325 |
||||
|
Task 3 calculations time sum = 0.991652 |
||||
|
Task 2 calculations time sum = 0.991980 |
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 3.369928 |
||||
|
|
||||
|
Number of points = 9000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 8999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 communications time sum = 0.001696 |
||||
|
Task 0 calculations time sum = 3.367163 |
||||
|
Task 1 communications time sum = 0.001609 |
||||
|
Task 1 calculations time sum = 3.368111 |
||||
|
Task 2 communications time sum = 0.001736 |
||||
|
Task 2 calculations time sum = 3.358565 |
||||
|
Task 3 communications time sum = 0.001776 |
||||
|
Task 3 calculations time sum = 3.337365 |
@ -0,0 +1,10 @@ |
|||||
|
Wall clock time = 0.033778 |
||||
|
|
||||
|
Number of points = 1000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 calculations time sum = 0.033493 |
||||
|
Task 1 calculations time sum = 0.033525 |
||||
|
Task 2 calculations time sum = 0.033579 |
||||
|
Task 3 calculations time sum = 0.033483 |
@ -0,0 +1,10 @@ |
|||||
|
Wall clock time = 7.247777 |
||||
|
|
||||
|
Number of points = 13000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 12999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 calculations time sum = 7.246494 |
||||
|
Task 1 calculations time sum = 7.226297 |
||||
|
Task 2 calculations time sum = 7.165253 |
||||
|
Task 3 calculations time sum = 7.173613 |
@ -0,0 +1,10 @@ |
|||||
|
Wall clock time = 12.712657 |
||||
|
|
||||
|
Number of points = 17000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 16999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 calculations time sum = 12.704461 |
||||
|
Task 1 calculations time sum = 12.666481 |
||||
|
Task 2 calculations time sum = 12.647987 |
||||
|
Task 3 calculations time sum = 12.703289 |
@ -0,0 +1,10 @@ |
|||||
|
Wall clock time = 19.683746 |
||||
|
|
||||
|
Number of points = 21000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 20999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 calculations time sum = 19.680478 |
||||
|
Task 1 calculations time sum = 19.611837 |
||||
|
Task 2 calculations time sum = 19.634485 |
||||
|
Task 3 calculations time sum = 19.678910 |
@ -0,0 +1,10 @@ |
|||||
|
Wall clock time = 0.990903 |
||||
|
|
||||
|
Number of points = 5000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 4999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 calculations time sum = 0.989757 |
||||
|
Task 1 calculations time sum = 0.990264 |
||||
|
Task 2 calculations time sum = 0.989132 |
||||
|
Task 3 calculations time sum = 0.988984 |
@ -0,0 +1,10 @@ |
|||||
|
Wall clock time = 3.374232 |
||||
|
|
||||
|
Number of points = 9000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 8999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 calculations time sum = 3.373230 |
||||
|
Task 1 calculations time sum = 3.370266 |
||||
|
Task 2 calculations time sum = 3.370403 |
||||
|
Task 3 calculations time sum = 3.343280 |
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 0.254555 |
||||
|
|
||||
|
Number of points = 1000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 communications time sum = 0.000763 |
||||
|
Task 0 calculations time sum = 0.253721 |
||||
|
Task 1 communications time sum = 0.000805 |
||||
|
Task 1 calculations time sum = 0.253366 |
||||
|
Task 2 communications time sum = 0.000442 |
||||
|
Task 3 communications time sum = 0.000690 |
||||
|
Task 3 calculations time sum = 0.253492 |
||||
|
Task 2 calculations time sum = 0.254101 |
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 554.284972 |
||||
|
|
||||
|
Number of points = 13000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 12999 |
||||
|
Number of tasks = 4 |
||||
|
Task 1 communications time sum = 7.297489 |
||||
|
Task 1 calculations time sum = 537.851630 |
||||
|
Task 2 communications time sum = 0.852826 |
||||
|
Task 2 calculations time sum = 541.811203 |
||||
|
Task 3 communications time sum = 2.411117 |
||||
|
Task 3 calculations time sum = 551.873807 |
||||
|
Task 0 communications time sum = 7.380732 |
||||
|
Task 0 calculations time sum = 540.423709 |
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 1239.585742 |
||||
|
|
||||
|
Number of points = 17000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 16999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 communications time sum = 15.438516 |
||||
|
Task 1 communications time sum = 8.418541 |
||||
|
Task 1 calculations time sum = 1209.574522 |
||||
|
Task 2 communications time sum = 1.685984 |
||||
|
Task 2 calculations time sum = 1234.917926 |
||||
|
Task 0 calculations time sum = 1209.477226 |
||||
|
Task 3 communications time sum = 14.000331 |
||||
|
Task 3 calculations time sum = 1225.585384 |
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 2344.181177 |
||||
|
|
||||
|
Number of points = 21000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 20999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 communications time sum = 14.015189 |
||||
|
Task 0 calculations time sum = 2310.925852 |
||||
|
Task 1 communications time sum = 9.007098 |
||||
|
Task 1 calculations time sum = 2323.463802 |
||||
|
Task 2 communications time sum = 8.904938 |
||||
|
Task 2 calculations time sum = 2326.644681 |
||||
|
Task 3 communications time sum = 22.523027 |
||||
|
Task 3 calculations time sum = 2321.658103 |
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 30.992809 |
||||
|
|
||||
|
Number of points = 5000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 4999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 communications time sum = 0.023125 |
||||
|
Task 0 calculations time sum = 30.965178 |
||||
|
Task 1 communications time sum = 0.010953 |
||||
|
Task 1 calculations time sum = 30.962624 |
||||
|
Task 3 communications time sum = 0.031227 |
||||
|
Task 3 calculations time sum = 30.945286 |
||||
|
Task 2 communications time sum = 0.009442 |
||||
|
Task 2 calculations time sum = 30.983349 |
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 183.127251 |
||||
|
|
||||
|
Number of points = 9000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 8999 |
||||
|
Number of tasks = 4 |
||||
|
Task 2 communications time sum = 1.622200 |
||||
|
Task 2 calculations time sum = 178.743481 |
||||
|
Task 0 communications time sum = 2.004348 |
||||
|
Task 0 calculations time sum = 179.725121 |
||||
|
Task 1 communications time sum = 0.820660 |
||||
|
Task 1 calculations time sum = 179.495873 |
||||
|
Task 3 communications time sum = 0.025997 |
||||
|
Task 3 calculations time sum = 183.101211 |
@ -0,0 +1,10 @@ |
|||||
|
Wall clock time = 0.254016 |
||||
|
|
||||
|
Number of points = 1000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 calculations time sum = 0.253394 |
||||
|
Task 1 calculations time sum = 0.253109 |
||||
|
Task 2 calculations time sum = 0.253625 |
||||
|
Task 3 calculations time sum = 0.253049 |
@ -0,0 +1,10 @@ |
|||||
|
Wall clock time = 554.383816 |
||||
|
|
||||
|
Number of points = 13000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 12999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 calculations time sum = 540.464332 |
||||
|
Task 1 calculations time sum = 537.962039 |
||||
|
Task 2 calculations time sum = 541.793609 |
||||
|
Task 3 calculations time sum = 551.988150 |
@ -0,0 +1,10 @@ |
|||||
|
Wall clock time = 1239.115736 |
||||
|
|
||||
|
Number of points = 17000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 16999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 calculations time sum = 1208.784077 |
||||
|
Task 3 calculations time sum = 1225.380272 |
||||
|
Task 1 calculations time sum = 1209.585533 |
||||
|
Task 2 calculations time sum = 1234.820747 |
@ -0,0 +1,10 @@ |
|||||
|
Wall clock time = 2344.109723 |
||||
|
|
||||
|
Number of points = 21000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 20999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 calculations time sum = 2312.102511 |
||||
|
Task 3 calculations time sum = 2321.945771 |
||||
|
Task 1 calculations time sum = 2323.699373 |
||||
|
Task 2 calculations time sum = 2326.662573 |
@ -0,0 +1,10 @@ |
|||||
|
Wall clock time = 30.982453 |
||||
|
|
||||
|
Number of points = 5000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 4999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 calculations time sum = 30.969539 |
||||
|
Task 1 calculations time sum = 30.962273 |
||||
|
Task 2 calculations time sum = 30.971577 |
||||
|
Task 3 calculations time sum = 30.943259 |
@ -0,0 +1,10 @@ |
|||||
|
Wall clock time = 183.099425 |
||||
|
|
||||
|
Number of points = 9000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 8999 |
||||
|
Number of tasks = 4 |
||||
|
Task 1 calculations time sum = 179.513594 |
||||
|
Task 2 calculations time sum = 178.732463 |
||||
|
Task 3 calculations time sum = 183.089220 |
||||
|
Task 0 calculations time sum = 179.690826 |
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 0.041514 |
||||
|
|
||||
|
Number of points = 1000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 999 |
||||
|
Number of tasks = 4 |
||||
|
Task 1 communications time sum = 0.000242 |
||||
|
Task 0 communications time sum = 0.000279 |
||||
|
Task 0 calculations time sum = 0.034408 |
||||
|
Task 1 calculations time sum = 0.033503 |
||||
|
Task 2 communications time sum = 0.000257 |
||||
|
Task 2 calculations time sum = 0.033410 |
||||
|
Task 3 communications time sum = 0.000291 |
||||
|
Task 3 calculations time sum = 0.033405 |
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 7.268335 |
||||
|
|
||||
|
Number of points = 13000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 12999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 communications time sum = 0.002351 |
||||
|
Task 0 calculations time sum = 7.265863 |
||||
|
Task 1 communications time sum = 0.004165 |
||||
|
Task 1 calculations time sum = 7.224932 |
||||
|
Task 2 communications time sum = 0.004251 |
||||
|
Task 3 communications time sum = 0.004838 |
||||
|
Task 3 calculations time sum = 7.167590 |
||||
|
Task 2 calculations time sum = 7.179096 |
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 12.761921 |
||||
|
|
||||
|
Number of points = 17000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 16999 |
||||
|
Number of tasks = 4 |
||||
|
Task 1 communications time sum = 0.012452 |
||||
|
Task 1 calculations time sum = 12.639010 |
||||
|
Task 0 communications time sum = 0.012091 |
||||
|
Task 0 calculations time sum = 12.700233 |
||||
|
Task 2 communications time sum = 0.002621 |
||||
|
Task 2 calculations time sum = 12.628114 |
||||
|
Task 3 communications time sum = 0.003257 |
||||
|
Task 3 calculations time sum = 12.677528 |
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 19.775075 |
||||
|
|
||||
|
Number of points = 21000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 20999 |
||||
|
Number of tasks = 4 |
||||
|
Task 1 communications time sum = 0.005514 |
||||
|
Task 0 communications time sum = 0.004735 |
||||
|
Task 0 calculations time sum = 19.683603 |
||||
|
Task 1 calculations time sum = 19.580722 |
||||
|
Task 2 communications time sum = 0.003601 |
||||
|
Task 2 calculations time sum = 19.653215 |
||||
|
Task 3 communications time sum = 0.006058 |
||||
|
Task 3 calculations time sum = 19.681204 |
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 1.021175 |
||||
|
|
||||
|
Number of points = 5000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 4999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 communications time sum = 0.001141 |
||||
|
Task 0 calculations time sum = 0.989849 |
||||
|
Task 1 communications time sum = 0.000935 |
||||
|
Task 1 calculations time sum = 0.990729 |
||||
|
Task 2 communications time sum = 0.001140 |
||||
|
Task 2 calculations time sum = 0.990895 |
||||
|
Task 3 communications time sum = 0.001201 |
||||
|
Task 3 calculations time sum = 0.989548 |
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 3.417923 |
||||
|
|
||||
|
Number of points = 9000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 8999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 communications time sum = 0.001669 |
||||
|
Task 0 calculations time sum = 3.369588 |
||||
|
Task 1 communications time sum = 0.003304 |
||||
|
Task 1 calculations time sum = 3.366839 |
||||
|
Task 2 communications time sum = 0.003461 |
||||
|
Task 2 calculations time sum = 3.383239 |
||||
|
Task 3 communications time sum = 0.003489 |
||||
|
Task 3 calculations time sum = 3.329598 |
@ -0,0 +1,10 @@ |
|||||
|
Wall clock time = 0.033758 |
||||
|
|
||||
|
Number of points = 1000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 calculations time sum = 0.033505 |
||||
|
Task 1 calculations time sum = 0.033490 |
||||
|
Task 2 calculations time sum = 0.033499 |
||||
|
Task 3 calculations time sum = 0.033585 |
@ -0,0 +1,10 @@ |
|||||
|
Wall clock time = 7.252139 |
||||
|
|
||||
|
Number of points = 13000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 12999 |
||||
|
Number of tasks = 4 |
||||
|
Task 2 calculations time sum = 7.167104 |
||||
|
Task 3 calculations time sum = 7.181140 |
||||
|
Task 0 calculations time sum = 7.248803 |
||||
|
Task 1 calculations time sum = 7.227046 |
@ -0,0 +1,10 @@ |
|||||
|
Wall clock time = 12.725699 |
||||
|
|
||||
|
Number of points = 17000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 16999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 calculations time sum = 12.721062 |
||||
|
Task 1 calculations time sum = 12.651490 |
||||
|
Task 2 calculations time sum = 12.608332 |
||||
|
Task 3 calculations time sum = 12.688143 |
@ -0,0 +1,10 @@ |
|||||
|
Wall clock time = 19.680875 |
||||
|
|
||||
|
Number of points = 21000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 20999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 calculations time sum = 19.672720 |
||||
|
Task 2 calculations time sum = 19.675402 |
||||
|
Task 3 calculations time sum = 19.676451 |
||||
|
Task 1 calculations time sum = 19.610648 |
@ -0,0 +1,10 @@ |
|||||
|
Wall clock time = 0.990137 |
||||
|
|
||||
|
Number of points = 5000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 4999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 calculations time sum = 0.989447 |
||||
|
Task 2 calculations time sum = 0.988779 |
||||
|
Task 1 calculations time sum = 0.988890 |
||||
|
Task 3 calculations time sum = 0.988694 |
@ -0,0 +1,10 @@ |
|||||
|
Wall clock time = 3.371798 |
||||
|
|
||||
|
Number of points = 9000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 8999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 calculations time sum = 3.366320 |
||||
|
Task 1 calculations time sum = 3.370863 |
||||
|
Task 2 calculations time sum = 3.353532 |
||||
|
Task 3 calculations time sum = 3.341214 |
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 0.010062 |
||||
|
|
||||
|
Number of points = 1000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 10 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 communications time sum = 0.000249 |
||||
|
Task 1 communications time sum = 0.000260 |
||||
|
Task 1 calculations time sum = 0.009729 |
||||
|
Task 0 calculations time sum = 0.009775 |
||||
|
Task 2 communications time sum = 0.000198 |
||||
|
Task 2 calculations time sum = 0.009810 |
||||
|
Task 3 communications time sum = 0.000267 |
||||
|
Task 3 calculations time sum = 0.009795 |
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 1.632057 |
||||
|
|
||||
|
Number of points = 13000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 10 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 communications time sum = 0.003166 |
||||
|
Task 0 calculations time sum = 1.628881 |
||||
|
Task 1 communications time sum = 0.001151 |
||||
|
Task 1 calculations time sum = 1.629646 |
||||
|
Task 2 communications time sum = 0.004368 |
||||
|
Task 2 calculations time sum = 1.626288 |
||||
|
Task 3 communications time sum = 0.003222 |
||||
|
Task 3 calculations time sum = 1.626732 |
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 2.793898 |
||||
|
|
||||
|
Number of points = 17000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 10 |
||||
|
Number of tasks = 4 |
||||
|
Task 3 communications time sum = 0.002752 |
||||
|
Task 3 calculations time sum = 2.789319 |
||||
|
Task 0 communications time sum = 0.008707 |
||||
|
Task 0 calculations time sum = 2.783873 |
||||
|
Task 1 communications time sum = 0.001881 |
||||
|
Task 1 calculations time sum = 2.790198 |
||||
|
Task 2 communications time sum = 0.004918 |
||||
|
Task 2 calculations time sum = 2.788967 |
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 4.295281 |
||||
|
|
||||
|
Number of points = 21000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 10 |
||||
|
Number of tasks = 4 |
||||
|
Task 1 communications time sum = 0.014575 |
||||
|
Task 1 calculations time sum = 4.275249 |
||||
|
Task 2 communications time sum = 0.008623 |
||||
|
Task 2 calculations time sum = 4.286643 |
||||
|
Task 3 communications time sum = 0.013051 |
||||
|
Task 3 calculations time sum = 4.274712 |
||||
|
Task 0 communications time sum = 0.012873 |
||||
|
Task 0 calculations time sum = 4.274911 |
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 0.241691 |
||||
|
|
||||
|
Number of points = 5000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 10 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 communications time sum = 0.000871 |
||||
|
Task 0 calculations time sum = 0.240815 |
||||
|
Task 1 communications time sum = 0.000740 |
||||
|
Task 1 calculations time sum = 0.240827 |
||||
|
Task 2 communications time sum = 0.000799 |
||||
|
Task 2 calculations time sum = 0.240844 |
||||
|
Task 3 communications time sum = 0.000831 |
||||
|
Task 3 calculations time sum = 0.240832 |
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 0.781440 |
||||
|
|
||||
|
Number of points = 9000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 10 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 communications time sum = 0.002033 |
||||
|
Task 0 calculations time sum = 0.779372 |
||||
|
Task 1 communications time sum = 0.001762 |
||||
|
Task 1 calculations time sum = 0.779503 |
||||
|
Task 2 communications time sum = 0.001510 |
||||
|
Task 2 calculations time sum = 0.779920 |
||||
|
Task 3 communications time sum = 0.002699 |
||||
|
Task 3 calculations time sum = 0.778432 |
@ -0,0 +1,10 @@ |
|||||
|
Wall clock time = 0.009180 |
||||
|
|
||||
|
Number of points = 1000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 10 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 calculations time sum = 0.009056 |
||||
|
Task 1 calculations time sum = 0.009083 |
||||
|
Task 2 calculations time sum = 0.009078 |
||||
|
Task 3 calculations time sum = 0.009072 |
@ -0,0 +1,10 @@ |
|||||
|
Wall clock time = 1.514796 |
||||
|
|
||||
|
Number of points = 13000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 10 |
||||
|
Number of tasks = 4 |
||||
|
Task 3 calculations time sum = 1.513576 |
||||
|
Task 0 calculations time sum = 1.510294 |
||||
|
Task 1 calculations time sum = 1.511106 |
||||
|
Task 2 calculations time sum = 1.509252 |
@ -0,0 +1,10 @@ |
|||||
|
Wall clock time = 2.596288 |
||||
|
|
||||
|
Number of points = 17000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 10 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 calculations time sum = 2.588859 |
||||
|
Task 1 calculations time sum = 2.594717 |
||||
|
Task 2 calculations time sum = 2.589177 |
||||
|
Task 3 calculations time sum = 2.590838 |
@ -0,0 +1,10 @@ |
|||||
|
Wall clock time = 3.991685 |
||||
|
|
||||
|
Number of points = 21000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 10 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 calculations time sum = 3.977723 |
||||
|
Task 3 calculations time sum = 3.969148 |
||||
|
Task 1 calculations time sum = 3.978771 |
||||
|
Task 2 calculations time sum = 3.979802 |
@ -0,0 +1,10 @@ |
|||||
|
Wall clock time = 0.224615 |
||||
|
|
||||
|
Number of points = 5000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 10 |
||||
|
Number of tasks = 4 |
||||
|
Task 1 calculations time sum = 0.223706 |
||||
|
Task 2 calculations time sum = 0.224058 |
||||
|
Task 3 calculations time sum = 0.224238 |
||||
|
Task 0 calculations time sum = 0.223671 |
@ -0,0 +1,10 @@ |
|||||
|
Wall clock time = 0.727053 |
||||
|
|
||||
|
Number of points = 9000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 10 |
||||
|
Number of tasks = 4 |
||||
|
Task 2 calculations time sum = 0.724410 |
||||
|
Task 3 calculations time sum = 0.723391 |
||||
|
Task 0 calculations time sum = 0.725784 |
||||
|
Task 1 calculations time sum = 0.724022 |
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 0.045668 |
||||
|
|
||||
|
Number of points = 1000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 communications time sum = 0.000274 |
||||
|
Task 0 calculations time sum = 0.036621 |
||||
|
Task 1 communications time sum = 0.000273 |
||||
|
Task 1 calculations time sum = 0.033439 |
||||
|
Task 2 communications time sum = 0.000280 |
||||
|
Task 2 calculations time sum = 0.033491 |
||||
|
Task 3 communications time sum = 0.000281 |
||||
|
Task 3 calculations time sum = 0.033490 |
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 7.269148 |
||||
|
|
||||
|
Number of points = 13000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 12999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 communications time sum = 0.002356 |
||||
|
Task 0 calculations time sum = 7.266687 |
||||
|
Task 1 communications time sum = 0.003331 |
||||
|
Task 1 calculations time sum = 7.232499 |
||||
|
Task 2 communications time sum = 0.003731 |
||||
|
Task 3 communications time sum = 0.004815 |
||||
|
Task 3 calculations time sum = 7.168525 |
||||
|
Task 2 calculations time sum = 7.207633 |
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 12.774908 |
||||
|
|
||||
|
Number of points = 17000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 16999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 communications time sum = 0.007294 |
||||
|
Task 1 communications time sum = 0.005029 |
||||
|
Task 1 calculations time sum = 12.661872 |
||||
|
Task 0 calculations time sum = 12.767496 |
||||
|
Task 2 communications time sum = 0.013357 |
||||
|
Task 2 calculations time sum = 12.607397 |
||||
|
Task 3 communications time sum = 0.002359 |
||||
|
Task 3 calculations time sum = 12.691293 |
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 19.765704 |
||||
|
|
||||
|
Number of points = 21000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 20999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 communications time sum = 0.007475 |
||||
|
Task 0 calculations time sum = 19.758115 |
||||
|
Task 1 communications time sum = 0.006529 |
||||
|
Task 1 calculations time sum = 19.593806 |
||||
|
Task 2 communications time sum = 0.002654 |
||||
|
Task 2 calculations time sum = 19.628838 |
||||
|
Task 3 communications time sum = 0.005116 |
||||
|
Task 3 calculations time sum = 19.667014 |
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 1.015355 |
||||
|
|
||||
|
Number of points = 5000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 4999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 communications time sum = 0.001099 |
||||
|
Task 0 calculations time sum = 0.991580 |
||||
|
Task 1 communications time sum = 0.001112 |
||||
|
Task 1 calculations time sum = 0.988937 |
||||
|
Task 2 communications time sum = 0.001104 |
||||
|
Task 2 calculations time sum = 0.990494 |
||||
|
Task 3 communications time sum = 0.001151 |
||||
|
Task 3 calculations time sum = 0.989527 |
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 3.409903 |
||||
|
|
||||
|
Number of points = 9000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 8999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 communications time sum = 0.001667 |
||||
|
Task 0 calculations time sum = 3.370045 |
||||
|
Task 1 communications time sum = 0.003079 |
||||
|
Task 1 calculations time sum = 3.392497 |
||||
|
Task 2 communications time sum = 0.003777 |
||||
|
Task 2 calculations time sum = 3.351902 |
||||
|
Task 3 communications time sum = 0.003148 |
||||
|
Task 3 calculations time sum = 3.338251 |
@ -0,0 +1,10 @@ |
|||||
|
Wall clock time = 0.033655 |
||||
|
|
||||
|
Number of points = 1000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 calculations time sum = 0.033443 |
||||
|
Task 1 calculations time sum = 0.033401 |
||||
|
Task 2 calculations time sum = 0.033422 |
||||
|
Task 3 calculations time sum = 0.033523 |
@ -0,0 +1,10 @@ |
|||||
|
Wall clock time = 7.260061 |
||||
|
|
||||
|
Number of points = 13000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 12999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 calculations time sum = 7.258476 |
||||
|
Task 1 calculations time sum = 7.228553 |
||||
|
Task 2 calculations time sum = 7.168067 |
||||
|
Task 3 calculations time sum = 7.180212 |
@ -0,0 +1,10 @@ |
|||||
|
Wall clock time = 12.724300 |
||||
|
|
||||
|
Number of points = 17000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 16999 |
||||
|
Number of tasks = 4 |
||||
|
Task 1 calculations time sum = 12.662180 |
||||
|
Task 2 calculations time sum = 12.674517 |
||||
|
Task 3 calculations time sum = 12.691427 |
||||
|
Task 0 calculations time sum = 12.715927 |
@ -0,0 +1,10 @@ |
|||||
|
Wall clock time = 19.714659 |
||||
|
|
||||
|
Number of points = 21000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 20999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 calculations time sum = 19.677347 |
||||
|
Task 1 calculations time sum = 19.646248 |
||||
|
Task 2 calculations time sum = 19.695513 |
||||
|
Task 3 calculations time sum = 19.708906 |
@ -0,0 +1,10 @@ |
|||||
|
Wall clock time = 0.990623 |
||||
|
|
||||
|
Number of points = 5000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 4999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 calculations time sum = 0.989279 |
||||
|
Task 1 calculations time sum = 0.989294 |
||||
|
Task 2 calculations time sum = 0.990020 |
||||
|
Task 3 calculations time sum = 0.989884 |
@ -0,0 +1,10 @@ |
|||||
|
Wall clock time = 3.376398 |
||||
|
|
||||
|
Number of points = 9000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 8999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 calculations time sum = 3.375470 |
||||
|
Task 1 calculations time sum = 3.372552 |
||||
|
Task 2 calculations time sum = 3.354796 |
||||
|
Task 3 calculations time sum = 3.335200 |
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 0.254555 |
||||
|
|
||||
|
Number of points = 1000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 communications time sum = 0.000763 |
||||
|
Task 0 calculations time sum = 0.253721 |
||||
|
Task 1 communications time sum = 0.000805 |
||||
|
Task 1 calculations time sum = 0.253366 |
||||
|
Task 2 communications time sum = 0.000442 |
||||
|
Task 3 communications time sum = 0.000690 |
||||
|
Task 3 calculations time sum = 0.253492 |
||||
|
Task 2 calculations time sum = 0.254101 |
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 554.284972 |
||||
|
|
||||
|
Number of points = 13000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 12999 |
||||
|
Number of tasks = 4 |
||||
|
Task 1 communications time sum = 7.297489 |
||||
|
Task 1 calculations time sum = 537.851630 |
||||
|
Task 2 communications time sum = 0.852826 |
||||
|
Task 2 calculations time sum = 541.811203 |
||||
|
Task 3 communications time sum = 2.411117 |
||||
|
Task 3 calculations time sum = 551.873807 |
||||
|
Task 0 communications time sum = 7.380732 |
||||
|
Task 0 calculations time sum = 540.423709 |
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 1239.585742 |
||||
|
|
||||
|
Number of points = 17000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 16999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 communications time sum = 15.438516 |
||||
|
Task 1 communications time sum = 8.418541 |
||||
|
Task 1 calculations time sum = 1209.574522 |
||||
|
Task 2 communications time sum = 1.685984 |
||||
|
Task 2 calculations time sum = 1234.917926 |
||||
|
Task 0 calculations time sum = 1209.477226 |
||||
|
Task 3 communications time sum = 14.000331 |
||||
|
Task 3 calculations time sum = 1225.585384 |
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 30.992809 |
||||
|
|
||||
|
Number of points = 5000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 4999 |
||||
|
Number of tasks = 4 |
||||
|
Task 0 communications time sum = 0.023125 |
||||
|
Task 0 calculations time sum = 30.965178 |
||||
|
Task 1 communications time sum = 0.010953 |
||||
|
Task 1 calculations time sum = 30.962624 |
||||
|
Task 3 communications time sum = 0.031227 |
||||
|
Task 3 calculations time sum = 30.945286 |
||||
|
Task 2 communications time sum = 0.009442 |
||||
|
Task 2 calculations time sum = 30.983349 |
@ -0,0 +1,14 @@ |
|||||
|
Wall clock time = 183.127251 |
||||
|
|
||||
|
Number of points = 9000 |
||||
|
Number of dimensions = 30 |
||||
|
Number of neighbors = 8999 |
||||
|
Number of tasks = 4 |
||||
|
Task 2 communications time sum = 1.622200 |
||||
|
Task 2 calculations time sum = 178.743481 |
||||
|
Task 0 communications time sum = 2.004348 |
||||
|
Task 0 calculations time sum = 179.725121 |
||||
|
Task 1 communications time sum = 0.820660 |
||||
|
Task 1 calculations time sum = 179.495873 |
||||
|
Task 3 communications time sum = 0.025997 |
||||
|
Task 3 calculations time sum = 183.101211 |
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue