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