我正在计算一张图片,并且正在使用OpenMPI将循环分布到几个内核上。 每个核心都正确计算了循环的一部分,但是合并了 核心0上的两个数组都导致部分图片为黑色。
我不知道发送/接收char数组是否破坏了数据或 如果我的合并不正确。 (我的虚拟机有2个内核)。
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <xmmintrin.h>
#include "complex.h"
#include "lodepng.h"
using namespace std;
#include <sys/time.h>
#include <mpi.h>
int julia(int width, int height, int x, int y, const complex &c, const int max_iter) {
/*
* calculates the number of iterations (between 0 and 255) for a pixel (x,y)
*/
complex z(1.5f * (x - width / 2) / (0.5f * width), (y - height / 2) / (0.5f * height));
int n = 0;
for (int i = 0; ((z.abs() < 2.0f) && (i < max_iter)); i++) {
float tmp = z.re() * z.re() - z.im() * z.im() + c.re();
z.set_im(2.0f * z.re() * z.im() + c.im());
z.set_re(tmp);
n++;
}
return max_iter - n;
}
int main(int argc, char **argv) {
int rank, num_procs;
//Initialize the infrastructure necessary for coomunication
MPI_Init(&argc, &argv);
//Identify this process
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
//Find out how many processes are active
MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
const complex c(-0.7, 0.27015); // pretty
// const complex c( -0.8, 0.156); // alternative complex number
const int width = 2 * 1024, height = 2 * 1024; // image size
int max_iter = 256;
// Allocate aligned image buffer
unsigned char *image = NULL;
int err = posix_memalign((void **) &image, 64, width * height * 4 * sizeof(unsigned char));
if (err){
cout << "[Error] Couldn't allocate memory for regular Image." << endl;
}
int count = height / num_procs;
int remainder = height % num_procs;
int start, stop;
if (rank < remainder) {
// The first 'remainder' ranks get 'count + 1' tasks each
start = rank * (count + 1);
stop = start + count;
} else {
// The remaining 'size - remainder' ranks get 'count' task each
start = rank * count + remainder;
stop = start + (count - 1);
}
/*
* Creates a pictures of a julia set
*/
cout << "--------------------- " << endl;
cout << "my rank " << rank << endl;
cout << "number of procs " << num_procs << endl;
cout << "start " << start << endl;
cout << "end " << stop << endl;
cout << "--------------------- "<< endl;
// iterate over image pixels and calculate their value
for (int y = start; y <= stop; y++) {
for (int x = 0; x < width; x++) {
int a = julia(width, height, x, y, c, max_iter);
image[4 * width * y + 4 * (x + 0) + 0] = a; // R
image[4 * width * y + 4 * (x + 0) + 1] = a; // G
image[4 * width * y + 4 * (x + 0) + 2] = a; // B
image[4 * width * y + 4 * (x + 0) + 3] = 255; // Alpha
}
}
if(rank != 0)
{
//send image to rank 0
MPI_Send(image, sizeof(image), MPI_UNSIGNED_CHAR, 0, 0, MPI_COMM_WORLD);
}
if(rank == 0 && (num_procs > 0))
{
// Allocate aligned image buffer
unsigned char *lImage = (unsigned char *) malloc(width * height * 4 * sizeof(unsigned char));
/*
unsigned char *lImage = NULL;
int err = posix_memalign((void **) &lImage, 64, width * height * 4 * sizeof(unsigned char));
if (err){
cout << "[Error] Couldn't allocate memory for regular Image." << endl;
}
*/
for(int i = 1; i < num_procs; i++)
{
//lImage receives the image array from process i
MPI_Recv(lImage, sizeof(lImage), MPI_UNSIGNED_CHAR, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
//calculate start and stop for the following for loop
int lCount = height / num_procs;
int lRemainder = height % num_procs;
int lStart, lStop;
if (i < lRemainder) {
// The first 'remainder' ranks get 'count + 1' tasks each
lStart = i * (lCount + 1);
lStop = lStart + lCount;
} else {
// The remaining 'size - remainder' ranks get 'count' task each
lStart = i * lCount + lRemainder;
lStop = lStart + (lCount - 1);
}
cout << "--------inside loop----------- " << endl;
cout << "my rank " << i << endl;
cout << "start " << lStart << endl;
cout << "end " << lStop << endl;
cout << "--------------------- "<< endl;
for (int y = lStart; y <= lStop; y++) {
for (int x = 0; x < width; x++) {
image[4 * width * y + 4 * (x + 0) + 0] = lImage[4 * width * y + 4 * (x + 0) + 0]; // R
image[4 * width * y + 4 * (x + 0) + 1] = lImage[4 * width * y + 4 * (x + 0) + 1]; // G
image[4 * width * y + 4 * (x + 0) + 2] = lImage[4 * width * y + 4 * (x + 0) + 2]; // B
image[4 * width * y + 4 * (x + 0) + 3] = 255; // Alpha
}
}
//receive image of the rank i
//merge received image array and rank 0 image array
}
free(lImage);
}
if(rank == 0)
{
/*Encode the image*/
unsigned error = lodepng_encode32_file("julia_openmp0.png", image, width, height);
if (error) {
std::cout << "[Error] " << error << " : " << lodepng_error_text(error) << std::endl;
}
}
if(rank == 1)
{
/*Encode the image*/
unsigned error = lodepng_encode32_file("julia_openmp1.png", image, width, height);
if (error) {
std::cout << "[Error] " << error << " : " << lodepng_error_text(error) << std::endl;
}
}
/*cleanup*/
free(image);
/* Tear down the communication infrastructure */
MPI_Finalize();
return 0;
答案 0 :(得分:0)
对不起,我没有机会进行适当的检查,但我认为这可以归结为这一行:
MPI_Recv(lImage, sizeof(lImage), MPI_UNSIGNED_CHAR, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
您正在尝试以特定顺序接收消息(过程1,过程2),而您实际上并不知道首先准备好哪个消息。并且MPI_Recv
的接收操作被阻止。您可以尝试以不依赖于计算顺序的方式来重写逻辑吗?一种方法是使用MPI_Gather()
。另一种选择是在您发送的消息中包含进程号,然后使用MPI_ANY_SOURCE
接收下一条传入消息,并在循环中使用进程号正确处理该阻止。