很早就想总结自己最近做的,然后一直拖拖到了现在。先总结先MPI多线程所学到的。先给一个简单的多线程实例,这是对图片多重采样的代码,在图片读取采样的时候采用MPI多线程进行编码。
bool DataCreater::creat_temp_data2(QStringList files, QString dst, int level_total, int begin_level, int image_begin)
{
QStringList file_temp_list;//图片列表
if (iscreattemp0 == true)
{
file_temp_list = updata_src_file_list(dst, begin_level - 1);//the function is used to updata image list
}
else
{
if (begin_level == 1)
file_temp_list = files;
else
file_temp_list = updata_src_file_list(dst, begin_level - 1);
}
QStringList file_temp_list_next_level;
QString dst_temp = dst;
QString str2;
int width = 0, height = 0;
int processI;
int numprocs;
int flag = 1;
int flgb = 0;
int flag_message[2] = { 0,0 };//interprocess communication signal,fist parameter is process ID,the second parameter is task ID.
int proc_file_num = 0;
MPI_Comm_rank(MPI_COMM_WORLD, &processI);//process ID
MPI_Comm_size(MPI_COMM_WORLD, &numprocs);//process number
int value_proc[200];
MPI_Status status;// dynamic transmission variable
for (int level_temp = begin_level; level_temp <= level_total; level_temp++)
{
//log file
std::string block_id_path = dst.toStdString();
block_id_path = block_id_path + "/log.txt";
std::ofstream ofresult(block_id_path.c_str(), std::ios::trunc);
ofresult << 0 << std::endl;//represent write temp file
ofresult << level_temp << std::endl;//represent write temp level
const char *path;
QByteArray text = file_temp_list.at(0).toLocal8Bit();
path = text.data();
TIFFSetWarningHandler(0);
TIFF *tif = TIFFOpen(path, "r");
if (tif == 0) {
printf(" open TIFF file %s failed\n", path);
return false;
}
TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &width);
TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &height);
TIFFClose(tif);
int sub_x = int(ceil(width / 2.0));
int sub_y = int(ceil(height / 2.0));
uint8 *buffer_slice = new uint8[size_t(width)* size_t(height)];
uint8 *sub_buffer = new uint8[size_t(sub_x)*size_t(sub_y)];
uint8 *sub_buffer_odd = new uint8[size_t(sub_x)*sub_y];
uint8 *sub_buffer_even = new uint8[size_t(sub_x)*sub_y];
for (int i = 0; i < numprocs; i++)
{
value_proc[i] = 0;
}
//the process 0 is used to publish task
if (processI == 0)
{
for (int j = 1+ image_begin; j < numprocs+ image_begin; j++)//image_begin is image begin ID,It can be considered as 0
{
flag = (j - 1) * 2;
MPI_Send(&flag, 1, MPI_INT, j- image_begin, 0, MPI_COMM_WORLD);//this will be introduced later in detail
std::cout << "Temp " << level_temp << " data processing slice " << BOLDGREEN << flag << RESET << " ---- " << file_temp_list.size() + (numprocs - 1) * 2 - 2 << '\r';
//printf("Temp %d data processing slice %d----%d\r",level_temp,flag,file_temp_list.size()+(numprocs-1)*2-2);
value_proc[j]++;
}
//for (int file_index = 9800;file_index<file_temp_list.size()+(numprocs-1)*2;file_index+=2)
for (int file_index = (numprocs - 1+ image_begin) * 2; file_index < file_temp_list.size() + (numprocs - 1) * 2; file_index += 2)
{
MPI_Recv(&flag_message, 2, MPI_INT, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
int flag_procID = flag_message[0];
flag = file_index;
if (flag_message[1]== file_temp_list.size() - 1)
{
ofresult << flag_message[1] << std::endl;
}
else
{
ofresult << flag_message[1] << std::endl;
ofresult << flag_message[1] + 1 << std::endl;
}
MPI_Send(&flag, 1, MPI_INT, flag_procID, 0, MPI_COMM_WORLD);
value_proc[flag_procID]++;
std::cout << "Temp " << level_temp << " data processing slice " << BOLDGREEN << flag << RESET << " ---- " << file_temp_list.size() + (numprocs - 1) * 2 - 2 << '\r';
}
printf("\n");
for (int i = 0; i < numprocs; i++)
{
// printf(" process %d files from node %d \n",value_proc[i],i);
}
}
else
{
while (1)
{
MPI_Recv(&flgb, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, &status);//This is used to establish a connection for the first time,may be can establish connection direct,this fuction will introduce later
if (flgb >= file_temp_list.size())
{
break;
}
//printf(" is resampling slice %d\n",flgb);
const char *path;
QByteArray text = file_temp_list.at(flgb).toLocal8Bit();
path = text.data();
load_slice_image_line(path, buffer_slice, width, height);
slice_resample(buffer_slice, sub_buffer_odd, width, height);
if (flgb == file_temp_list.size() - 1)
{
for (int index_ddd = 0; index_ddd < size_t(sub_x)*sub_y; index_ddd++)
{
sub_buffer[index_ddd] = sub_buffer_odd[index_ddd];
}
}
else
{
const char *path2;
QByteArray text2 = file_temp_list.at(flgb + 1).toLocal8Bit();
path2 = text2.data();
load_slice_image_line(path2, buffer_slice, width, height);
slice_resample(buffer_slice, sub_buffer_even, width, height);
for (size_t index_ddd = 0; index_ddd < size_t(sub_x)*sub_y; index_ddd++)
{
sub_buffer[index_ddd] = (sub_buffer_odd[index_ddd] + sub_buffer_even[index_ddd]) / 2;
}
}
str2 = creat_temp_file_path(dst_temp, level_temp, flgb);
const QByteArray text2 = str2.toLocal8Bit();
const char *data = text2.data();
this->write8bitImage(data, sub_buffer, sub_x, sub_y);
//this->write_buffer(data,sub_buffer,sub_x,sub_y,1);
int *message = new int[2];
message[0] = processI;
message[1] = flgb;
MPI_Send(message, 2, MPI_INT, 0, 0, MPI_COMM_WORLD);
}
}
MPI_Barrier(MPI_COMM_WORLD);//wait all process arrive here
image_begin = 0;
file_temp_list.clear();
file_temp_list = updata_src_file_list(dst_temp, level_temp);
ofresult.close();
}
return true;
}
下面介绍一下两个主要通信函数
MMPI_Send(
void* data,//发送的数据,一般是指针
int count, //发送指针后面多少个数据
MPI_Datatype datatype,//数据类型
int destination,//发送给哪个进程
int tag,//通信标签
MPI_Comm communicator)//发送进程的通信子
int MPI_Recv(
void* msg_buf_p, 接收数据
int buf_size, 数据个数
MPI_Datatype buf_type, 数据类型
int source, 数据来源进程
int tag, 通信标签
MPI_Comm communicator, 通信子,与想接收进程这个变量相同
MPI_Status* status_p /* OUT */
);
通过这些可以简单了解MPI的使用,详细还需进一步学习。