Я пытаюсь изучить MPI, поэтому я создал эту простую программу, которая выполняет свертку на изображении uint8 в градациях серого. Я изменил код openMP, который работал вполне нормально, с нарезкой векторизованного изображения на части для каждого процессора - scatterDataSize, но я получаю странную ошибку из MPI:
"Первичное задание завершилось нормально, но 1 процесс вернулся
ненулевой код выхода. По указанию пользователя задание было прервано.
mpirun заметил, что процесс ранга 1 с PID 5360 на узле wn25 завершился по сигналу 11 (ошибка сегментации). "
Я пытался сделать это с помощью MPI_Scatter, чтобы передавать изображение всем процессам, а после свертки собирать данные с помощью MPI_Gather или MPI_Allgather, но результат обоих одинаков ...
argv - размеры изображения - изображения, например, input1000_800.bin, поэтому программа выполняется как:
mpirun -np 4 ./main 1000 800 и исходный код моей программы:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <omp.h>
#include <mpi.h>
const int ROOT = 0;
const double filter[][5] = { {0,0,1,0,0},
{0,1,2,1,0},
{1,2,-16,2,1},
{0,1,2,1,0},
{0,0,1,0,0} };
unsigned char normalize(double value);
double convolution(int i, int j, unsigned char *image, int height, int width, int filterDimension);
void saveImage(char* filename[], unsigned char* image, long fileLength);
long getFileSize(char* filename[]);
unsigned char * readImage(char* filename[]);
int main(int argc, char * argv[])
{
int width = atoi(argv[1]);
int height = atoi(argv[2]);
const char * prefixInFile = "../../labMPI/infile";
const char * prefixOutFile = "result";
const char * fileExtension = ".bin";
char outFileName[64], fileName[64];
unsigned char * image, *buffer, *data;
long fileSize;
int processorsAmount, processId, scatterDataSize;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &processorsAmount);
MPI_Comm_rank(MPI_COMM_WORLD, &processId);
strcpy(fileName, prefixInFile);
strcat(fileName, argv[1]);
strcat(fileName, "_");
strcat(fileName, argv[2]);
strcat(fileName, fileExtension);
strcpy(outFileName, prefixOutFile);
strcat(outFileName, argv[1]);
strcat(outFileName, "_");
strcat(outFileName, argv[2]);
strcat(outFileName, fileExtension);
fileSize = getFileSize(fileName);
data = (unsigned char *)malloc(fileSize * sizeof(unsigned char));
scatterDataSize = fileSize / processorsAmount;
int startPoint = scatterDataSize * processId;
int endPoint = scatterDataSize * (processId + 1);
printf("filesize: %d\nprocessorsAmount: %d\niam: %d\nscatterDataSize: %d\nstartPoint: %d\nendPoint: %d\n",
fileSize, processorsAmount, processId, scatterDataSize, startPoint, endPoint);
if (processId == ROOT)
{
printf("Reading file %s on ROOT \n output file will be: %s \n", fileName, outFileName);
image = readImage(fileName);
}
MPI_Bcast(image,fileSize, MPI_UNSIGNED_CHAR, ROOT, MPI_COMM_WORLD);
#pragma omp parallel for
for (int i = startPoint; i < endPoint; i++)
{
register int col = i % width;
register int row = i / width;
register long idx = col + width * row;
data[idx] = normalize(convolution(col, row, image, height, width, 5));
}
/* i am not sure how to collect processed data on workers back to root and perform save */
MPI_Bcast(data,fileSize, MPI_UNSIGNED_CHAR, ROOT, MPI_COMM_WORLD);
if (processId == ROOT)
{
saveImage(outFileName, data, fileSize);
printf("Image processing is finished");
free(image);
}
free(data);
MPI_Finalize();
return 0;
}
double convolution(int i, int j, unsigned char *image, int height, int width, int filterDimension)
{
register int filterHeight, filterWidth, kernelCenter, ii, jj;
filterHeight = filterWidth = filterDimension;
kernelCenter = filterHeight / 2;
register double tmp = 0;
for (long m = 0; m < filterHeight; ++m) {
for (long n = 0; n < filterWidth; ++n) {
ii = i + (kernelCenter - m);
jj = j + (kernelCenter - n);
if (ii >= 0 && ii < width && jj >= 0 && jj < height)
tmp += image[jj * width + ii] * filter[m][n];
}
}
return tmp;
}
unsigned char * readImage(char* filename[])
{
FILE *inFile = fopen(filename, "rb");
fseek(inFile, 0, SEEK_END);
long long fileLength = ftell(inFile);
fseek(inFile, 0, SEEK_SET);
unsigned char * image = (unsigned char *)malloc(fileLength * sizeof(unsigned char));
fread(image, sizeof(unsigned char), fileLength, inFile);
fclose(inFile);
return image;
}
long getFileSize(char* filename[])
{
FILE *inFile = fopen(filename, "rb");
fseek(inFile, 0, SEEK_END);
long fileLength = ftell(inFile);
fclose(inFile);
return fileLength;
}
void saveImage(char* filename[], unsigned char* image, long fileLength)
{
FILE *write = fopen(filename, "wb");
fwrite(image, sizeof(unsigned char), fileLength * sizeof(unsigned char), write);
fclose(write);
}
unsigned char normalize(double value)
{
if (value > 255)
{
value = 255;
}
else if (value < 0) {
value = 0;
}
return (unsigned char)value;
}