Для чего нужен start и finalize в main функции C++
Изучаю код на языке C++, но не могу разобраться для чего в функции main есть start и finalize. Я не так хорошо знаю C++, но все же необходимо разобрать код, но впервые вижу такие конструкции, подскажите, пожалуйста, что это и для чего?
int main(int argc, char **argv)
{
MPI_Init(NULL, NULL);
// Find out rank, size
int instance_rank;
MPI_Comm_rank(MPI_COMM_WORLD, &instance_rank);
int world_size;
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
char* tracefile;
tracefile = getenv("TVTRACE");
if( tracefile != NULL ){
printf( "tv tracefile=%s\n", tracefile);
MPI_Pcontrol(TRACEFILES, NULL, tracefile, 0);
}
else{
MPI_Pcontrol(TRACEFILES, NULL, "trace", 0);
}
MPI_Pcontrol(TRACELEVEL, 1,1,1);
MPI_Pcontrol(TRACENODE, 1000000, 0, 1);
MPI_Status status;
start:
printf("Instance rank: %d, world_size: %d. Start\n", instance_rank, world_size);
// Время для замеров
double start_time, end_time, delta;
start_time = MPI_Wtime();
ProcessInitData pid;
int i, j, k;
//Здесь код симплекс метода
if(instance_rank == 0){
SimplexTable st = init_random_simplex_table(2, 3);
print_matrix("table", st.table, st.m + 1, st.m + st.n);
print_vector("table z", st.z, st.m + 1);
print_vector("table b", st.b, st.m + 1);
int row_length = st.n + st.m;
//чтобы получилось обработать и нечетно количество условий
int max_rows_per_proc = (st.m + 1) / world_size;
double *q;
q = malloc(sizeof(double) * (row_length));
for(i = 0; i < row_length; i++){
q[i] = st.table[0][i];
}
MPI_Pcontrol(TRACEEVENT, "entry", 1, 0, "");
for(i = 0; i < world_size; i++){
ProcessInitData data;
data = get_process_init_data(st, max_rows_per_proc, row_length, i);
//рассылаем данные слейвам
if(i > 0){
send_process_init_data(data, i);
} else {
pid = data;
}
}
MPI_Pcontrol(TRACEEVENT, "exit", 1, 0, "");
//тут уже параллельность
while(1){
int column = -1;
//смотрим только по количеству переменных
for(i = 0; i < st.n; i++){
if(q[i] < 0){
column = i;
break;
}
}
MPI_Pcontrol(TRACEEVENT, "entry", 2, 0, "");
//рассылаем всем column, он же признак завершения работы всего
MPI_Bcast(&column, 1, MPI_INT, instance_rank, MPI_COMM_WORLD);
if(column < 0){
break;
}
MPI_Pcontrol(TRACEEVENT, "exit", 2, 0, "");
//работаем сами
ProcessWorkResult work_res;
work_res = process_work(pid, column);
//получаем результаты, выбираем лучший
int min_L = 0;
MPI_Pcontrol(TRACEEVENT, "entry", 3, 0, "");
ProcessWorkResult any_process_res, best_work_res = work_res;
for(i=1; i < world_size; i++){
any_process_res = recieve_process_work_result(i, &status);
if(any_process_res.min_X < best_work_res.min_X){
best_work_res = any_process_res;
min_L = i;
}
}
MPI_Pcontrol(TRACEEVENT, "exit", 3, 0, "");
//сообщаем слевам, кто лучший
MPI_Bcast(&min_L, 1, MPI_INT, instance_rank, MPI_COMM_WORLD);
double *g;
double h;
MPI_Pcontrol(TRACEEVENT, "entry", 4, 0, "");
if(min_L != 0){
//лучший процесс - один из слейвов
//ждем g и h
g = malloc(sizeof(double) * (pid.col_count));
MPI_Bcast(g, pid.col_count, MPI_DOUBLE, min_L, MPI_COMM_WORLD);
MPI_Bcast(&(h), 1, MPI_DOUBLE, min_L, MPI_COMM_WORLD);
} else {
//лучший процесс - мастер
//отпрака всем g=С[row_no] и h=b[row_no]
g = pid.C[best_work_res.row_no];
h = pid.b[best_work_res.row_no];
MPI_Bcast(g, pid.col_count, MPI_DOUBLE, instance_rank, MPI_COMM_WORLD);
MPI_Bcast(&(h), 1, MPI_DOUBLE, instance_rank, MPI_COMM_WORLD);
}
MPI_Pcontrol(TRACEEVENT, "exit", 4, 0, "");
//а здесь у нас уже есть g и h
//изменяем C и b
if (min_L == instance_rank){
//особенности процесса с минимумом
for(i = 0; i < row_length; i++){
pid.C[best_work_res.row_no][i] = g[i]/g[column];
}
pid.b[best_work_res.row_no] = h / g[column];
}
//особенности мастера
double a;
if(g[column] != 0){
a = q[column] / g[column];
} else {
a = 0;
}
for(i = 0; i < row_length; i++){
q[i] = q[i] - (a * g[i]);
}
st.z[0] = st.z[0] - a * h;
}
for(i = 0; i < row_length; i++){
st.table[0][i] = q[i];
}
MPI_Pcontrol(TRACEEVENT, "entry", 5, 0, "");
for(k = 0; k < world_size; k++){
ProcessInitData data;
int max_rows_per_proc;
if(!k){
data = pid;
max_rows_per_proc = pid.row_count;
} else {
data = recieve_process_init_data(k, &status);
}
for(i = 0; i < data.row_count; i++){
int row_index = k * max_rows_per_proc + i + 1;
for(j = 0; j < data.col_count; j++){
st.table[row_index][j] = data.C[i][j];
}
st.z[row_index] = data.b[i];
}
if(k != 0)
{
free_matrix(data.C, data.row_count);
free_vector(data.b);
}
}
MPI_Pcontrol(TRACEEVENT, "exit", 5, 0, "");
// print_matrix("table", st.table, st.m + 1, st.m + st.n);
print_vector("table z", st.z, st.m + 1);
// print_vector("table b", st.b, st.m + 1);
//чистим данные!!!
free_matrix(st.table, st.m + 1);
free_vector(st.z);
free_vector(st.b);
} else {
//получаем информацию для инициализации
MPI_Pcontrol(TRACEEVENT, "entry", 6, 0, "");
pid = recieve_process_init_data(0, &status);
MPI_Pcontrol(TRACEEVENT, "exit", 6, 0, "");
while(1){
int column;
//получаем column или финалайз
MPI_Bcast(&(column), 1, MPI_INT, 0, MPI_COMM_WORLD);
printf("Instance %d, column %d\n", instance_rank, column);
if(column < 0){
break;
}
ProcessWorkResult work_res;
work_res = process_work(pid, column);
//шлем результат мастеру
send_process_work_result(work_res, 0);
//получаем min_L
int min_L;
MPI_Bcast(&(min_L), 1, MPI_INT, 0, MPI_COMM_WORLD);
double *g;
double h;
MPI_Pcontrol(TRACEEVENT, "entry", 7, 0, "");
if(min_L != instance_rank){
//лучший процесс не мы
//ждем g и h
g = malloc(sizeof(double) * (pid.col_count));
MPI_Bcast(g, pid.col_count, MPI_DOUBLE, min_L, MPI_COMM_WORLD);
MPI_Bcast(&(h), 1, MPI_DOUBLE, min_L, MPI_COMM_WORLD);
} else {
//лучший процесс - мы
//отпрака всем g=С[row_no] и h=b[row_no]
g = pid.C[work_res.row_no];
h = pid.b[work_res.row_no];
MPI_Bcast(g, pid.col_count, MPI_DOUBLE, instance_rank, MPI_COMM_WORLD);
MPI_Bcast(&(h), 1, MPI_DOUBLE, instance_rank, MPI_COMM_WORLD);
}
MPI_Pcontrol(TRACEEVENT, "exit", 7, 0, "");
//а здесь у нас уже есть g и h
//изменяем C и b
//особенность процесс с минимумом
if(min_L == instance_rank){
for(i = 0; i < pid.col_count; i++){
pid.C[work_res.row_no][i] = g[i]/g[column];
}
pid.b[work_res.row_no] = h / g[column];
}
if(min_L != instance_rank){
free_vector(g);
}
}
//отсылаем C и b
MPI_Pcontrol(TRACEEVENT, "entry", 8, 0, "");
send_process_init_data(pid, 0);
MPI_Pcontrol(TRACEEVENT, "exit", 8, 0, "");
//чистим данные
free_matrix(pid.C, pid.row_count);
free_vector(pid.b);
}
finalize:
end_time = MPI_Wtime();
delta = end_time - start_time;
printf("Instance rank: %d, finished for %lf seconds\n", instance_rank, delta);
//finalizing
MPI_Finalize();
return EXIT_SUCCESS;
}
Источник: Stack Overflow на русском