MPI基本图像处理-使用MPI进行卷积

时间:2019-01-12 23:49:05

标签: c image-processing mpi

我试图学习MPI,所以我创建了这个简单的程序,用于对uint8灰度图像进行卷积。我修改了openMP代码,该代码运行得很好,将每个处理器的矢量化图像切成多个部分-设置为scatterDataSize,但是我从MPI中得到了奇怪的错误:

“主作业正常终止,但是返回了1个进程 非零退出代码。按照用户的指示,作业已中止。

mpirun注意到在节点wn25上具有PID 5360的进程等级1在信号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;
}

0 个答案:

没有答案