我已经收集了它,仍然无法工作。我输入它时挂起...我已经尝试再次尝试使用MPI_gatherv,此代码中的每个位置。我没有得到正确的代码。这是MPI_gatherv我放的最后一个。
#include<iostream>
#include<mpi.h>
#include<cmath>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
int xGradient(Mat image, int x, int y)
{
return ((int)(image.at<uchar>(y-1, x-1))) +
2*image.at<uchar>(y, x-1) +
image.at<uchar>(y+1, x-1) -
image.at<uchar>(y-1, x+1) -
2*image.at<uchar>(y, x+1) -
image.at<uchar>(y+1, x+1);
}
int yGradient(Mat image, int x, int y)
{
return ((int)(image.at<uchar>(y-1, x-1))) +
2*image.at<uchar>(y-1, x) +
image.at<uchar>(y-1, x+1) -
image.at<uchar>(y+1, x-1) -
2*image.at<uchar>(y+1, x) -
image.at<uchar>(y+1, x+1);
}
int main()
{
Mat src, grey, dst;
Mat grey2;
double start, end;
int gx, gy, sum, argc, awal,akhir, size, rank;
int i;
int recvcounts[4] = { 0, 1, 2, 3 };
int displ[4] = { 0, 0, 1, 3 };
int buffer[6];
size_t total;
size_t elemsize;
int sizes[3];
int master=0;
char **argv;
awal= MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if( rank == master )
{
//start=MPI_Wtime();
src= imread("E:/sobel/Debug/jari.jpg");
cvtColor(src,grey,CV_BGR2GRAY);
src.release();
dst = grey.clone();
total=grey.total();
sizes[2]=grey.elemSize();
cv::Size s = grey.size();
sizes[0] = s.height;
sizes[1] = s.width;
cout<<"citra terdiri dari "<<total<<" elements dengan ukuran yaitu "<<sizes[0]<<" x "<<sizes[1]<<endl;
if( !grey.data )
{ return -1; }
//start=MPI_Wtime();
}
//if( rank == master )
start=MPI_Wtime();
MPI_Bcast( sizes, 3, MPI_INT, 0, MPI_COMM_WORLD);
// cout<<"rank "<<rank<<" : "<<sizes[0]<<" x "<<sizes[1]<<endl;
if(rank!=master){
grey.create(sizes[0],sizes[1],CV_8U);
}
MPI_Bcast( grey.data, sizes[0]*sizes[1], MPI_CHAR, 0, MPI_COMM_WORLD);
grey2.create(sizes[0],sizes[1],CV_8U);
int starty=(rank*grey.rows/size);
if(starty==0)
{starty=1;}
int stopy=((rank+1)*grey.rows/size);
if(stopy>grey.rows - 1)
{stopy=grey.rows - 1;}
for(int y = starty; y < stopy; y++)
{
for(int x = 1; x < grey.cols - 1; x++)
{
gx = xGradient(grey, x, y);
gy = yGradient(grey, x, y);
sum = abs(gx) + abs(gy);
sum = sum > 255 ? 255:sum;
sum = sum < 0 ? 0 : sum;
grey2.at<uchar>(y,x) = sum;
}
}
for (i=0; i<rank; i++)
{
buffer[i] = rank;
}
recvcounts[i]=grey.cols*(grey.rows/size);
displ[i+1]=displ[i]+recvcounts[i];
MPI_Gatherv(buffer, rank, MPI_INT,buffer, recvcounts, displ, MPI_INT, 0, MPI_COMM_WORLD);
if (rank == 0)
{
for (i=0; i<6; i++)
fflush(stdout);
}
grey.release();
imwrite("E:/sobel/Debug/deteksi tepi mpi.jpg", grey2);
//grey2.release();
end=MPI_Wtime();
cout<<"rank "<<rank<<" : waktu eksekusi sobel MPI adalah : "<< end-start << " detik " <<endl;
akhir=MPI_Finalize();
//waitKey();
return 0;
}
我在[i](红色下划线)出错了
int recvcounts[i]=grey.cols*(grey.rows/size);
int displ[i+1]=displ[i]+recvcounts[i];
我该怎么做?请帮我修理一下。我用4 processus执行代码时挂起了
答案 0 :(得分:1)
在MPI中,将指针发送到对象是不可能的。与线程或openmp不同,默认行为是并行的。如果您撰写imwrite(name, grey2 );
,则图片grey2
将被写入size
次。如果将指针grey
从0发送到1,则proc 1上的grey
指针将指向proc 0拥有的内存。这可能会导致失败。
MPI为您提供了多种与MPI_Send()
和MPI_Receive()
进行通信的方式。例如,MPI_Bcast()
适合将图像从proc 0发送到所有proc。 http://www.mcs.anl.gov/research/projects/mpi/www/www3/MPI_Bcast.html
我通过首先发送图片大小然后再发送数据,将代码更改为使用MPI_Bcast()
。
#include<iostream>
#include<mpi.h>
#include<cmath>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
//int mod(int z, int l);
int xGradient(Mat image, int x, int y)
{
return ((int)(image.at<uchar>(y-1, x-1))) +
2*image.at<uchar>(y, x-1) +
image.at<uchar>(y+1, x-1) -
image.at<uchar>(y-1, x+1) -
2*image.at<uchar>(y, x+1) -
image.at<uchar>(y+1, x+1);
}
int yGradient(Mat image, int x, int y)
{
return ((int)(image.at<uchar>(y-1, x-1))) +
2*image.at<uchar>(y-1, x) +
image.at<uchar>(y-1, x+1) -
image.at<uchar>(y+1, x-1) -
2*image.at<uchar>(y+1, x) -
image.at<uchar>(y+1, x+1);
}
int main()
{
Mat src, grey, dst;
Mat grey2;
double start, end;
int gx, gy, sum, argc, awal,akhir, size, rank;
int master=0;
char **argv;
// MPI_Status status;
awal= MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
// start=MPI_Wtime();
cout<<"rank "<<rank<<endl;
size_t total;
size_t elemsize;
int sizes[3];
if( rank == master )
{
start=MPI_Wtime();
src= imread("jari1.jpg");
cvtColor(src,grey,CV_BGR2GRAY);
src.release();
//dst = grey.clone();
imwrite("jari2.jpg", grey );
cout<<"ok here"<<endl;
if(!grey.isContinuous()){
cout<<"trouble : data is not continuous"<<endl;
}
total=grey.total();
sizes[2]=grey.elemSize();
cv::Size s = grey.size();
sizes[0] = s.height;
sizes[1] = s.width;
cout<<"grey is made of "<<total<<" elements of size "<<sizes[2]<<" that is "<<sizes[0]<<" by "<<sizes[1]<<endl;
if( !grey.data )
{
return -1;
}
// MPI_Send(&grey, 1, MPI_LONG, 1, 1, MPI_COMM_WORLD);
cout<<"master mengirim data ke rank 1"<<endl;
//fflush (stdout);
}
/*else if (rank==1)
{
MPI_Recv(&grey, 1, MPI_LONG, 0, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
cout<<"rank 1 menerima data"<<endl;
}*/
MPI_Bcast( sizes, 3, MPI_INT, 0, MPI_COMM_WORLD);
cout<<rank<<" : "<<sizes[0]<<" "<<sizes[1]<<endl;
if(rank!=master){
grey.create(sizes[0],sizes[1],CV_8U);
if(!grey.data){
cout<<"data not allocated, rank "<<rank<<endl;
}else{
cout<<" ok !"<<endl;
}
}
MPI_Bcast( grey.data, sizes[0]*sizes[1], MPI_CHAR, 0, MPI_COMM_WORLD);
//for output
grey2.create(sizes[0],sizes[1],CV_8U);
char name[100];
sprintf(name,"jari%d.jpg",rank+42+size);
imwrite(name, grey );
/*
for(int y = 0; y < grey.rows; y++)
for(int x = 0; x < grey.cols; x++)
grey.at<uchar>(y,x) = 0;
*/
int starty=(rank*grey.rows/size);
if(starty==0)
{starty=1;}
int stopy=((rank+1)*grey.rows/size);
if(stopy>grey.rows - 1)
{stopy=grey.rows - 1;}
for(int y = starty; y < stopy; y++)
{
for(int x = 1; x < grey.cols - 1; x++)
{
gx = xGradient(grey, x, y);
gy = yGradient(grey, x, y);
sum = abs(gx) + abs(gy);
//cout<<sum<<endl;
sum = sum > 255 ? 255:sum;
sum = sum < 0 ? 0 : sum;
grey2.at<uchar>(y,x) = sum;
//cout<<sum<<endl;
}
}
grey.release();
//namedWindow("deteksi tepi sobel");
//imshow("deteksi tepi sobel", dst);
//namedWindow("grayscale");
//imshow("grayscale", grey);
//namedWindow("Original");
//imshow("Original", src);
sprintf(name,"jari%d.jpg",rank+42);
imwrite(name, grey2 );
grey2.release();
//MPI_Barrier(MPI_COMM_WORLD);
end=MPI_Wtime();
cout<<"time: "<< end-start << " detik " <<endl;
akhir=MPI_Finalize();
//waitKey();
return 0;
}
要检索proc 0上的数据,MPI_Gatherv()
函数似乎很有用。 http://www.mcs.anl.gov/research/projects/mpi/www/www3/MPI_Gatherv.html或http://mpi.deino.net/mpi_functions/MPI_Gatherv.html我让您继续使用您的代码。您可能需要对教程和示例进行扩展查看......
编辑:
我在很大程度上改变了代码,我希望这段代码能够结束你的任务......
我改变主意,用MPI_Scatterv()
在每个过程中发送一小部分图像。我也改变了渐变的计算...然后我使用MPI_Gatherv()
在一个proc上检索图像。最后,整体加速很低,因为它的大部分是花开放和写文件。而且,这样的滤波器(特别是这个代码......)需要一个大的存储带宽。
我担心你没有完全理解第一段代码是如何工作的。但这个还远未明确......我的索引有问题......
#include<iostream>
#include<mpi.h>
#include<cmath>
#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;
//int mod(int z, int l);
static inline int xGradient(Mat image, int x, int y)
{
return ((int)(image.at<uchar>(y-1, x-1))) +
2*image.at<uchar>(y, x-1) +
image.at<uchar>(y+1, x-1) -
image.at<uchar>(y-1, x+1) -
2*image.at<uchar>(y, x+1) -
image.at<uchar>(y+1, x+1);
}
static inline int yGradient(Mat image, int x, int y)
{
return ((int)(image.at<uchar>(y-1, x-1))) +
2*image.at<uchar>(y-1, x) +
image.at<uchar>(y-1, x+1) -
image.at<uchar>(y+1, x-1) -
2*image.at<uchar>(y+1, x) -
image.at<uchar>(y+1, x+1);
}
static inline int xGradientd(uchar* pt, int cols)
{
return ((int)(pt[-cols+1])+2*pt[1]+pt[cols+1]-pt[-cols-1]-2*pt[-1]-pt[cols-1]);
}
static inline int yGradientd(uchar* pt, int cols )
{
return ((int)(pt[cols-1])+2*pt[cols]+pt[cols+1]-pt[-cols-1]-2*pt[-cols]-pt[-cols+1]);
}
int main()
{
Mat src, grey, dst;
Mat grey2;
Mat grey3;
double start, end;
int gx, gy, sum, argc, awal,akhir, size, rank;
char **argv;
// MPI_Status status;
awal= MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
// start=MPI_Wtime();
cout<<"rank "<<rank<<endl;
size_t total;
size_t elemsize;
int sizes[3];
if( rank == 0)
{
start=MPI_Wtime();
src= imread("jari1.jpg");
cvtColor(src,grey,CV_BGR2GRAY);
src.release();
//dst = grey.clone();
imwrite("jari2.jpg", grey );
cout<<"ok here"<<endl;
if(!grey.isContinuous()){
cout<<"trouble : data is not continuous"<<endl;
}
total=grey.total();
sizes[2]=grey.elemSize();
cv::Size s = grey.size();
sizes[0] = s.height;
sizes[1] = s.width;
cout<<"grey is made of "<<total<<" elements of size "<<sizes[2]<<" that is "<<sizes[0]<<" by "<<sizes[1]<<endl;
if( !grey.data )
{
return -1;
}
// MPI_Send(&grey, 1, MPI_LONG, 1, 1, MPI_COMM_WORLD);
cout<<"master mengirim data ke rank 1"<<endl;
//fflush (stdout);
}
//start of parallel part. To this point, only proc 0 was working.
if( rank == 0 )
{
start=MPI_Wtime();
}
//the sizes of the image grey are send to all processus.
MPI_Bcast( sizes, 3, MPI_INT, 0, MPI_COMM_WORLD);
//cout<<rank<<" : "<<sizes[0]<<" "<<sizes[1]<<endl;
int recvcount[size];
int displ[size];
int i;
//compute size of local image
//on each proc, a little slice of the image will be received from proc 0 through MPI_Scatterv
//to compute the gradient, two extra lines should be send on top and bottom of slice.(except for 0 and sizes-1)
//this is why there are so many tests.
//how many pixels on the slice ? sendcount.
int sendcount=sizes[1]*(sizes[0]/size)+2*sizes[1];
if(rank==size-1){
sendcount=sizes[1]*(sizes[0]-(size-1)*(sizes[0]/size))+sizes[1];
}
if(rank==0){
sendcount-=sizes[1];
}
//printf("creating image %d %d \n",sendcount/sizes[1],sizes[1]);
//image allocation :
grey3.create(sendcount/sizes[1],sizes[1],CV_8U);
if(!grey3.data){
cout<<"data not allocated, rank "<<rank<<endl;
}else{
//cout<<" ok !"<<endl;
}
//compute sizes and offsets on proc 0
//how many char should be sent from proc 0 to proc i ? recvcount[i].
//where does the data starts ? displ[i].
//these information are needed by MPI_Scatterv() on proc 0
if(rank==0){
displ[0]=0;
for(i=0;i<size;i++){
recvcount[i]=grey.cols*(grey.rows/size)+grey.cols;
if(i>0){
recvcount[i]+=grey.cols;
}
if(i>0){
displ[i]=recvcount[i-1]+displ[i-1]-2*grey.cols;
}
}
recvcount[size-1]=grey.cols*(grey.rows-(size-1)*(grey.rows/size));
if(size>1){
recvcount[size-1]+=grey.cols;
}
if(size-1>0){
displ[size-1]=grey.cols*(grey.rows)-recvcount[size-1];
}
}
/*
if(rank==master){
for(i=0;i<size;i++){
printf("count %d displ %d \n",recvcount[i],displ[i]);
}
}
*/
MPI_Scatterv( grey.data, recvcount, displ, MPI_CHAR, grey3.data, sendcount,MPI_CHAR,0, MPI_COMM_WORLD);
/*
char name[100];
sprintf(name,"jariscat%d.jpg",rank);
imwrite(name, grey3 );
*/
//MPI_Bcast( grey.data, sizes[0]*sizes[1], MPI_CHAR, 0, MPI_COMM_WORLD);
//for output
//this local slice will store the result of the gradient operation
grey2.create(sendcount/sizes[1],sizes[1],CV_8U);
/*
for(int y = 0; y < grey.rows; y++)
for(int x = 0; x < grey.cols; x++)
grey.at<uchar>(y,x) = 0;
*/
int starty=(rank*sizes[0]/size);
if(starty==0)
{starty=1;}
int stopy=((rank+1)*sizes[0]/size);
if(stopy>sizes[0] - 1)
{stopy=sizes[0] - 1;}
int ii=grey3.cols;
uchar* data=grey3.data;
uchar* datad=grey2.data;
for(int y = starty; y < stopy; y++)
{
ii++;
for(int x = 1; x < sizes[1] - 1; x++)
{
//gx = xGradient(grey, x, y);
gx=xGradientd(&data[ii],grey2.cols);
gy=yGradientd(&data[ii],grey2.cols);
//gy = yGradient(grey, x, y);
//printf("%d %d \n",gx,gy);
sum = abs(gx) + abs(gy);
//cout<<sum<<endl;
sum = sum > 255 ? 255:sum;
sum = sum < 0 ? 0 : sum;
datad[ii] = sum;
//cout<<sum<<endl;
ii++;
}
ii++;
}
//namedWindow("deteksi tepi sobel");
//imshow("deteksi tepi sobel", dst);
//namedWindow("grayscale");
//imshow("grayscale", grey);
//namedWindow("Original");
//imshow("Original", src);
/*
sprintf(name,"jarigrad%d.jpg",rank);
imwrite(name, grey2 );
*/
// now, the data in grey2 should be sent from every processor in image grey on proc 0
//MPI_Gatherv will be used.
//on proc 0, count of bytes to be received from each processor should be computed
// as well as displacements representing where each part should be placed in image grey
if(rank==0){
displ[0]=0;
for(i=0;i<size;i++){
recvcount[i]=grey.cols*(grey.rows/size);
if(i>0){
displ[i]=recvcount[i-1]+displ[i-1];
}
}
recvcount[size-1]=grey.cols*(grey.rows-(size-1)*(grey.rows/size));
if(size-1>0){
displ[size-1]=recvcount[size-2]+displ[size-2];
}
}
//on each processor, how many lines should be sent ? sendcount.
//where does the data in grey2 starts ? tosend.
sendcount=sizes[1]*(sizes[0]/size);
if(rank==size-1){
sendcount=sizes[1]*(sizes[0]-(size-1)*(sizes[0]/size));
}
uchar* tosend=&grey2.data[grey2.cols];
if(rank==0){
tosend=&grey2.data[0];
}
MPI_Gatherv(tosend,sendcount , MPI_CHAR,grey.data, recvcount, displ,MPI_CHAR, 0, MPI_COMM_WORLD);
grey2.release();
//everything is back on proc 0 in image grey
end=MPI_Wtime();
if(rank==0){
imwrite("output.jpg", grey );
cout<<"time: "<< end-start << " detik " <<endl;
grey.release();
}
akhir=MPI_Finalize();
//waitKey();
return 0;
}
再见,
弗朗西斯