// CommCost.cpp: implementation of the CommCost class. // ////////////////////////////////////////////////////////////////////// #include #include "CommCost.h" #include "Vm.h" //==== #include "stdio.h" #include "Interval.h" #include "LoopBlock.h" //extern int ShdWid[10]; #include "ModelStructs.h" extern _ParLoopInfo ParLoopInfo; int ShdWid[10]; //=*** using namespace std; extern VM* rootVM; // pointer to root VM extern ofstream prot; extern _DArrayFlag * DAF_tmp; //==== void calculate(); double TStart, TByte; LoopBlock** ProcBlock; vector s, n; long x, y, z, LoopSZ; vector p, dmax, conv_beg, conv_end; int add, first; double time_c,time_x,call_time; int mode=0; //now mode=0 (no print) //was mode==0 (only global), 1(global+approach), 2(only approach), 3(global+aproach+no_print) int full_mode=0; //full_mode==0(as old dvm), 1(max_rank-pipeline calc(full search the best)) 2(different order of cycles for find the best in full search) vector pip, mult_is, mm; int mult,rank_mas,max_rank=4; //максимальный ранк моделируемого конвейера vector ord; //порядок запуска циклов int invers[10]; // 10 par loop inside each other //=*** #define min(a, b) (a < b ? a : b) #define max(a, b) (a > b ? a : b) /* #if defined (_MSC_VER) || (defined (__GNUG__) && (__GNUC__ < 3)) template T max(T a, T b) { return a >= b ? a : b; } #endif */ ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CommCost::CommCost() { vm = 0; lvector v(0); transfer = Dim2Array(0, v); } CommCost::~CommCost() { } CommCost::CommCost(VM *Avm) { lvector v(rootVM->GetLSize(), 0); vm = Avm; assert(vm != 0); #ifdef P_DEBUG // prot << *vm << endl; #endif transfer = Dim2Array(rootVM->GetLSize(), v); // инициализируется нулями } void CommCost::Update(DArray * oldDA, DArray * newDA) { long p1, p2, size; Block b1, b2, bi; long i, j; bool transferIs = false; vector transferInf((long) vm->Rank(), 0); vector SI(2,0L); long daRank = oldDA->Rank(); long amRank = oldDA->AM_Dis->Rank(); long vmRank = oldDA->AM_Dis->VM_Dis->Rank(); bool replAxisIs = false; long amAxis; long num; /* for(i=0; i ничего не надо пересылать { //printf("NOTHING to send!!!!!!!!!!!!!!!!!!\n"); return; } // printf("Start %d ok \n",daRank); //=*** vector replAxis(vmRank, 0); if (oldDA->Repl) { if (oldDA->AM_Dis == newDA->AM_Dis) return; for (i = 0; i < vm->Rank(); i++) { if (oldDA->AM_Dis->FillArr[i] > newDA->AM_Dis->FillArr[i]) { transferIs = true; } transferInf[i] = oldDA->AM_Dis->FillArr[i] - newDA->AM_Dis->FillArr[i]; } if (!transferIs) return; // printf("GGGOOOOD\n"); //grig b1 = Block(oldDA, 0); b1 = Block(oldDA, 0,1); //\grig // для 1-мерного случая if (vm->Rank() == 1) { p1=0; for ( p2 = 0; p2 < vm->GetSize(1) - oldDA->AM_Dis->FillArr[0]; p2++) { //grig b2 = Block(newDA, p2); b2 = Block(newDA, p2,1); //\grig bi = b1 ^ b2; size = bi.GetBlockSize(); transfer[p1][p2] += size * oldDA->TypeSize; } return; } // для 2-мерного случая if (transferInf[0] > 0 && transferInf[1] > 0) { // a) for (i = 0; i < vm->GetSize(2) - oldDA->AM_Dis->FillArr[1]; i++) for (j = vm->GetSize(1) - oldDA->AM_Dis->FillArr[0]; j < vm->GetSize(1) - newDA->AM_Dis->FillArr[0]; j++) { SI[0] = vm->GetSize(1) - oldDA->AM_Dis->FillArr[0] - 1; SI[1] = i; p1 = vm->GetLI(SI); SI[0] = j; SI[1] = i; p2 = vm->GetLI(SI); //grig b2 = Block(newDA, p2); b2 = Block(newDA, p2,1); //\grig bi = b1 ^ b2; size = bi.GetBlockSize(); transfer[p1][p2] += size * oldDA->TypeSize; } // b) for ( i = 0; i < vm->GetSize(1) - oldDA->AM_Dis->FillArr[0]; i++) for (j = vm->GetSize(2) - oldDA->AM_Dis->FillArr[1]; j < vm->GetSize(2) - newDA->AM_Dis->FillArr[1]; j++) { SI[0] = i; SI[1] = vm->GetSize(2) - oldDA->AM_Dis->FillArr[1] - 1; p1 = vm->GetLI(SI); SI[0] = i; SI[1] = j; p2 = vm->GetLI(SI); //grig b2 = Block(newDA, p2); b2 = Block(newDA, p2,1); //\grig bi = b1 ^ b2; size = bi.GetBlockSize(); transfer[p1][p2] += size * oldDA->TypeSize; } // c) SI[0] = vm->GetSize(1) - oldDA->AM_Dis->FillArr[0] - 1; SI[1] = vm->GetSize(2) - oldDA->AM_Dis->FillArr[1] - 1; p1 = vm->GetLI(SI); for (i = vm->GetSize(1) - oldDA->AM_Dis->FillArr[0]; i < vm->GetSize(1) - newDA->AM_Dis->FillArr[0]; i++) for (j = vm->GetSize(2) - oldDA->AM_Dis->FillArr[1]; j < vm->GetSize(2) - newDA->AM_Dis->FillArr[1]; j++) { SI[0] = i; SI[1] = j; p2 = vm->GetLI(SI); //grig b2 = Block(newDA, p2); b2 = Block(newDA, p2,1); //\grig bi = b1 ^ b2; size = bi.GetBlockSize(); transfer[p1][p2] += size * oldDA->TypeSize; } } else { if (transferInf[0] > 0) { for (i = 0; i < vm->GetSize(2) - newDA->AM_Dis->FillArr[1]; i++) for (j = vm->GetSize(1) - oldDA->AM_Dis->FillArr[0]; j < vm->GetSize(1) - newDA->AM_Dis->FillArr[0]; j++) { SI[0] = vm->GetSize(1) - oldDA->AM_Dis->FillArr[0] - 1; SI[1] = i; p1 = vm->GetLI(SI); SI[0] = j; SI[1] = i; p2 = vm->GetLI(SI); //grig b2 = Block(newDA, p2); b2 = Block(newDA, p2,1); //\grig bi = b1 ^ b2; size = bi.GetBlockSize(); transfer[p1][p2] += size * oldDA->TypeSize; } } else { for ( i = 0; i < vm->GetSize(1) - newDA->AM_Dis->FillArr[0]; i++) for (j = vm->GetSize(2) - oldDA->AM_Dis->FillArr[1]; j < vm->GetSize(2) - newDA->AM_Dis->FillArr[1]; j++) { SI[0] = i; SI[1] = vm->GetSize(2) - oldDA->AM_Dis->FillArr[1] - 1; p1 = vm->GetLI(SI); SI[0] = i; SI[1] = j; p2 = vm->GetLI(SI); //grig b2 = Block(newDA, p2); b2 = Block(newDA, p2,1); //\grig bi = b1 ^ b2; size = bi.GetBlockSize(); transfer[p1][p2] += size * oldDA->TypeSize; } } } return; } for (i = 0; i < vmRank; i++) { switch (oldDA->AM_Dis->DistRule[amRank + i].Attr) { case map_REPLICATE : replAxis[i] = 1; replAxisIs = true; break; case map_NORMVMAXIS : amAxis = oldDA->AM_Dis->DistRule[amRank + i].Axis; switch (oldDA->AlignRule[daRank + amAxis - 1].Attr) { case align_REPLICATE : replAxis[i] = 1; replAxisIs = true; break; case align_BOUNDREPL : replAxis[i] = 2; // Здесь нужна дополнительная информация - номера процессоров в этом измерении на которые DArray размножен replAxisIs = true; } break; } } // printf("UPDATE GOOD\n"); // для 2-мерного случая(считаю, что BOUNDREPL для 1-мерной машины нет, // для 2-мерной пока тоже) следовательно REPLICATE только по одному какому-то измерению if (replAxisIs) { if (replAxis[0]) { // размножен по 1-му измерению // printf("UPDATE 1DIM\n"); for (j = 0; j < vm->GetSize(2); j++) { //grig b1 = Block(oldDA, vm->GetSpecLI(0, 2, j)); b1 = Block(oldDA, vm->GetSpecLI(0, 2, j),1); //\grig for (p2 = 0; p2 < vm->GetLSize(); p2++) { //grig b2 = Block(newDA, p2); b2 = Block(newDA, p2,1); //\grig bi = b1 ^ b2; num = vm->GetNumInDim(p2, 1); printf("Num=%d Block=%d-%d %d-%d %d-%d \n",num,b1.GetLower(0),b1.GetUpper(0),b1.GetLower(1),b1.GetUpper(1),b1.GetLower(2),b1.GetUpper(2)); if (num > (vm->GetSize(1) - oldDA->AM_Dis->FillArr[0] - 1)) SI[0] = vm->GetSize(1) - oldDA->AM_Dis->FillArr[0] - 1; else SI[0] = num; SI[1] = j; printf("j=%d p2=%d SI=[%d %d]\n",j,p2,SI[0],SI[1]); p1 = vm->GetLI(SI); if (p1 != p2) transfer[p1][p2] += bi.GetBlockSize() * oldDA->TypeSize; } } } else { for (j = 0; j < vm->GetSize(1); j++) { //grig b1 = Block(oldDA, vm->GetSpecLI(0, 1, j)); b1 = Block(oldDA, vm->GetSpecLI(0, 1, j),1); //\grig for (p2 = 0; p2 < vm->GetLSize(); p2++) { //grig // b2 = Block(newDA, p2); b2 = Block(newDA, p2,1); //\grig bi = b1 ^ b2; num = vm->GetNumInDim(p2, 2); if (num > (vm->GetSize(2) - oldDA->AM_Dis->FillArr[1] - 1)) SI[1] = vm->GetSize(2) - oldDA->AM_Dis->FillArr[1] - 1; else SI[1] = num; SI[0] = j; p1 = vm->GetLI(SI); if (p1 != p2) transfer[p1][p2] += bi.GetBlockSize() * oldDA->TypeSize; } } } return; } // случай когда массив до пере... ни как не размножен ни по одному из измерений // (в общем виде) for (p1 = 0; p1 < vm->GetLSize(); p1++) { //grig b1 = Block(oldDA, p1); b1 = Block(oldDA, p1,1); //\grig for (p2 = 0; p2 < vm->GetLSize(); p2++) { if (p1 != p2) { //grig b2 = Block(newDA, p2); b2 = Block(newDA, p2,1); //\grig bi = b1 ^ b2; size = bi.GetBlockSize(); transfer[p1][p2] += size * oldDA->TypeSize; // update } } } } CommCost & CommCost::operator =(const CommCost & cc) { this->transfer = cc.transfer; this->vm = cc.vm; return *this; } double CommCost::GetCost() { double cost = 0.0; long p1, p2; long Distance, maxDistance = 0; // текущее и максимальное растояние // (длина минимального пути между процессорами) // между процессорами long Byte, maxByte = 0; // -//- число пересылаемых байтов long s; // размер пересылаемой по конвейеру порции данных(в байтах) long k; // число порций long e; // остаток int c = 0; // 0 - если остаток = 0, 1 - иначе long LSize = rootVM->GetLSize(); assert(vm != NULL); double TStart = vm->getTStart(); double TByte = vm->getTByte(); switch (vm->getMType()) { case mach_ETHERNET: if (DAF_tmp == NULL) { for (p1 = 0; p1 < LSize; p1++) for (p2 = 0; p2 < LSize; p2++) if ((p1 != p2) && (transfer[p1][p2] != 0)) cost += TStart + TByte * transfer[p1][p2]; } //==== else { for (p1 = 0; p1 < LSize; p1++) DAF_tmp->ProcessTimeStamp[p1] = 0; for (p1 = 0; p1 < LSize; p1++) for (p2 = 0; p2 < LSize; p2++) if ((p1 != p2) && (transfer[p1][p2] != 0)) { cost += TStart + TByte * transfer[p1][p2]; DAF_tmp->ProcessTimeStamp[p1] = cost; //ждет конца копирования отправитель DAF_tmp->ProcessTimeStamp[p2] = cost; //ждет конца копирования получатель // printf("Trans %d -> %d = cost[%f]\n",p1,p2,cost); } } //=*** break; case mach_TRANSPUTER: // определение расстояния (минимального пути) до максимально // удаленных процессоров между которыми имеются пересылки for (p1 = 0; p1 < LSize; p1++) { for (p2 = 0; p2 < LSize; p2++) { Distance = vm->GetDistance(p1, p2); Byte = transfer[p1][p2]; if (Distance >= maxDistance && Byte != 0) { if (Distance > maxDistance) { maxDistance = Distance; maxByte = Byte; } else maxByte = max(Byte, maxByte); } } } // подсчет времени пересылки при использовании конвейера if (maxDistance != 0) { if (maxDistance != 1) { s = sqrt(TStart * maxByte / (TByte * (maxDistance - 1))); if (s > maxByte) s = maxByte; if (s == 0) s = 1; k = maxByte / s; e = maxByte % s; if (e != 0) c = 1; cost = (TStart + TByte * s) * (maxDistance + k - 1) + c * (TStart + TByte * e); } else cost = TStart + TByte * maxByte; } for (p1 = 0; p1 < LSize; p1++) DAF_tmp->ProcessTimeStamp[p1] = cost; //====// все ждут конца копирования break; case mach_MYRINET: //==== if (mode) { printf("Myrinet!!!\n"); for (p1 = 0; p1 < LSize; p1++) { for (p2 = 0; p2 < LSize; p2++) printf("%d\t", transfer[p1][p2]); printf("\n"); } } //=*** for (p1 = 1; p1 < LSize; p1++) { for (p2 = 0; p2 < p1; p2++) { if (transfer[p1][p2] < transfer[p2][p1]) { transfer[p1][p2] = transfer[p2][p1]; } } } if (DAF_tmp == NULL) { for (p1 = 1; p1 < LSize; p1++) for (p2 = 0; p2 < p1; p2++) if ((p1 != p2) && (transfer[p1][p2] != 0)) cost += TStart + TByte * transfer[p1][p2]; } //==== else { for (p1 = 0; p1 < LSize; p1++) DAF_tmp->ProcessTimeStamp[p1] = 0; for (p1 = 1; p1 < LSize; p1++) for (p2 = 0; p2 < p1; p2++) if ((p1 != p2) && (transfer[p1][p2] != 0)) { cost += TStart + TByte * transfer[p1][p2]; DAF_tmp->ProcessTimeStamp[p1] += cost; //ждет конца копирования получатель DAF_tmp->ProcessTimeStamp[p2] += cost; //ждет конца копирования отправитель // printf("Trans %d -> %d = cost[%f]\n",p2,p1,TStart + TByte * transfer[p1][p2]); } } //=*** break; } const int procC = vm->getProcCount(); const int numCh = vm->getNumChanels(); cost = (procC < numCh) ? cost / procC : cost / numCh; return cost * vm->getScale(); } //=========================================================================== //#define min(a,b) ((ab)?a:b) #define mbeg(i,j) ((jLSDim[j].Lower:0) #define mend(i,j) ((jLSDim[j].Upper:0) #define mstep(i,j) ((jLSDim[j].Step:1) #define msize(i,j) ((jLSDim[j].Upper - ProcBlock[i]->LSDim[j].Lower + 1) / ProcBlock[i]->LSDim[j].Step:1) #define bsize(i,j,z) ((msize(i,j)%z)?msize(i,j)/z+1:msize(i,j)/z) #define for_calc(n,k,beg,end) for(n[k]=invers[k]?end:beg; invers[k]?n[k]>=beg:n[k]<=end; invers[k]?n[k]--:n[k]++) #define ShdWid(k) ((!invers[k])?ParLoopInfo.SGnew->BoundGroup_Obj->dimInfo[k].LeftBSize:ParLoopInfo.SG->BoundGroup_Obj->dimInfo[k].RightBSize) #define PreShdWid(k) (invers[k]?ParLoopInfo.SGnew->BoundGroup_Obj->dimInfo[k].LeftBSize:ParLoopInfo.SG->BoundGroup_Obj->dimInfo[k].RightBSize) //internal functions double calc_comm(long i) { long k,m; double res; long *save_n; save_n=(long *)malloc(max_rank*sizeof(long)); if (i==max_rank) { for(k=1,m=ShdWid[n[0]];k prev, b, post; //mode=0; //ord[0]=1; ord[1]=0; ord[2]=2; ord[3]=3; //s[0]=1; s[1]=11; s[2]=1; s[3]=1; prev.resize(max_rank); post.resize(max_rank); n.resize(max_rank); b.resize(max_rank); //prev = (long *)malloc(max_rank * sizeof(long)); //post = (long *)malloc(max_rank * sizeof(long)); //n = (long *)malloc(max_rank * sizeof(long)); //b = (long *)malloc(max_rank * sizeof(long)); comm = (float **)malloc(MPSProcCount() * sizeof(float *)); for (i = 0; i < MPSProcCount(); i++) if (ProcBlock[i]->GetRank()) comm[i] = (float *)malloc(max_rank * sizeof(float)); //printf("Step %d %d %d\n",mstep(0,0),mstep(0,1),mstep(0,2)); //printf("Invers %d %d %d\n",invers[0],invers[1],invers[2]); if (rank_mas >= 2) //was 3 { float *****a, m, mwait, *com; float **prev_comm, sz[4][4][4][4]; //max_rank=4; хранит размеры блоков текущего процессора float beg, step, last; int ind_beg; double time_beg; double last_real_comm, real_comm; int pip_ord[4]; //для корректного вычисления prev и post com = (float *)malloc(MPSProcCount() * sizeof(float)); prev_comm = (float **)malloc(max_rank * sizeof(float *)); for (i = 0; i < rank_mas; i++) prev_comm[i] = (float *)malloc(rank_mas * sizeof(float)); //почему 4: 1-2-3=начало а по 2-3 можно спрогнозировать конец=4 a = (float *****)malloc(MPSProcCount() * sizeof(float ****)); for (i = 0; i < MPSProcCount(); i++) if (ProcBlock[i]->GetRank()) a[i] = (float ****)malloc(4 * sizeof(float ***)); for (i = 0; i < MPSProcCount(); i++) if (ProcBlock[i]->GetRank()) for (n[0] = 0; n[0] < 4; n[0]++) a[i][n[0]] = (float ***)malloc(4 * sizeof(float **)); for (i = 0; i < MPSProcCount(); i++) if (ProcBlock[i]->GetRank()) for (n[0] = 0; n[0] < 4; n[0]++) for (n[1] = 0; n[1] < 4; n[1]++) a[i][n[0]][n[1]] = (float **)malloc(4 * sizeof(float *)); for (i = 0; i < MPSProcCount(); i++) if (ProcBlock[i]->GetRank()) for (n[0] = 0; n[0] < 4; n[0]++) for (n[1] = 0; n[1] < 4; n[1]++) for (n[2] = 0; n[2] < 4; n[2]++) a[i][n[0]][n[1]][n[2]] = (float *)malloc(4 * sizeof(float)); // printf("ms %d %d %d \n",bsize(0,0,s[0]),bsize(0,1,s[1]),bsize(0,2,s[2])); // printf("ALL=%d\n",LoopSZ); if (call_time / LoopSZ > 0.0000000001 && mode) printf("Send/Exec=%.f\n", (TStart + TByte) / (call_time / LoopSZ)); for (i = 0; i < MPSProcCount(); i++) if (ProcBlock[i]->GetRank()) for (n[0] = 0; n[0] < min(4, bsize(i, ord[0], s[ord[0]])); n[0]++) for (n[1] = 0; n[1] < min(4, bsize(i, ord[1], s[ord[1]])); n[1]++) for (n[2] = 0; n[2] < min(4, bsize(i, ord[2], s[ord[2]])); n[2]++) for (n[3] = 0; n[3] < min(4, bsize(i, ord[3], s[ord[3]])); n[3]++) { a[i][n[0]][n[1]][n[2]][n[3]] = 1; for (j = 0; j < 4; j++) if (n[j] < min(3, bsize(i, ord[j], s[ord[j]]) - 1)) a[i][n[0]][n[1]][n[2]][n[3]] *= s[j]; else a[i][n[0]][n[1]][n[2]][n[3]] *= (msize(i, j) % s[j]) ? msize(i, j) % s[j] : s[j]; // printf("%d-%d-%d-%d-%d=%.f\n",i,n[0],n[1],n[2],n[3],a[i][n[0]][n[1]][n[2]][n[3]]); } for (i = 0; i < MPSProcCount(); i++) { com[i] = 0; if (ProcBlock[i]->GetRank()) for (k = 0; k < max_rank; k++) comm[i][k] = 0; } //==== предварительный обсчет for (i = 0, time_c = 0; i < max_rank; i++) { for (k = 0; k < max_rank; k++) n[k] = ord[(i + k) % max_rank]; for (k = 1, m = pip[n[0]] - 1; k < max_rank; k++) m *= pip[n[k]]; if (m) time_c += m * calc_comm(1); } if (mode) printf("Communication::time_c=%.10f\n", time_c); for (i = 0, m = 0; i < MPSProcCount(); i++) if (ProcBlock[i]->GetRank()) m++; //printf("Time_comm=%f\n",time_c); // printf("wanna insuff %f ->> %f - %f comm=%f\n",call_time, cur*call_time/LoopSZ, call_time/m, time_c); if (add) { // AddMPSTime(__Wait_shadow, time_c/m); // AddMPSTime(__CPU_time_usr, call_time/LoopSZ); // AddMPSTime(__CPU_time_usr, call_time/(m*mult)); // AddMPSTime(__Insuff_parall_sys, (cur*call_time/LoopSZ-call_time/m)/mult-time_c/m); // AddMPSTime(__CPU_time_sys, cur*call_time/LoopSZ-call_time/m); } //=*** возможно это не точно но примерно верно рассчитывается объем вычислений и передач, а далее очень точно вычисляется когда закончится общее выполнение ind_beg = -1; for_calc(n, 0, conv_beg[0], conv_end[0]) //n[0] пробегает 1 измерение процов конвейера в порядке для вычисления блоков конвейера for_calc(n, 1, conv_beg[1], conv_end[1]) //n[1] пробегает 2 измерение процов конвейера ... for_calc(n, 2, conv_beg[2], conv_end[2]) //n[2] пробегает 3 измерение процов конвейера ... for_calc(n, 3, conv_beg[3], conv_end[3]) //n[3] пробегает 4 измерение процов конвейера ... { //only comment i=n[0]*p[1]*p[2]+n[1]*p[2]+n[2]; only comment for (k = 0, i = 0; k < rank_mas; k++) { for (j = k + 1, d = 1; j < rank_mas; j++) d *= p[j]; i += n[k] * d; } if (add) { for (j = 0, cur = 1; j < max_rank; j++) cur *= msize(i, j); // printf("proc[%d] cpu+=%f\n",i,cur*call_time/LoopSZ); AddTime(__CPU_time_usr, i, cur*call_time / LoopSZ); if (add == 2) AddTime(__Insuff_parall_usr, i, cur*call_time / LoopSZ); } if (ProcBlock[i]->GetRank()) { for (k = 0; k < rank_mas; k++) { for (j = k + 1, d = 1; j < rank_mas; j++) d *= p[j]; //надо prev == -1 если нет пред. процессора для него по этому измерению, кот. надо ждать if (invers[k]) if (n[k] != conv_end[k]/*pip[k]-1*/ && i + d < MPSProcCount() && ProcBlock[i + d]->GetRank()) prev[k] = i + d; else prev[k] = -1; else if (n[k] != conv_beg[k]/*0*/ && i - d >= 0 && ProcBlock[i - d]->GetRank()) prev[k] = i - d; else prev[k] = -1; if (!invers[k]) if (n[k] != conv_end[k]/*pip[k]-1*/ && i + d < MPSProcCount() && ProcBlock[i + d]->GetRank()) post[k] = i + d; else post[k] = -1; else if (n[k] != conv_beg[k]/*0*/ && i - d >= 0 && ProcBlock[i - d]->GetRank()) post[k] = i - d; else post[k] = -1; } if (ind_beg == -1) { // int tmp_shd_wid[4]; for (k = 0; k < max_rank; k++) { // tmp_shd_wid[k]=ShdWid[k]; // ShdWid[k]=0; pip_ord[k] = -1; } for (k = 0, d = 1; k < rank_mas; k++) { if (post[k] != -1) for (j = 0; j < rank_mas; j++) if (mbeg(i, j) != mbeg(post[k], j) || mend(i, j) != mend(post[k], j)) { //ShdWid[k]=tmp_shd_wid[j]; pip_ord[k] = j; } } } if (mode) { printf("PIPE ORDER [ProcDim -> ArrDim]"); {for (k = 0; k < max_rank; k++)if (pip_ord[k] != -1)printf(" %d -> %d ", k, pip_ord[k]); } printf("\n"); } { int old_prev[4], old_post[4]; for (k = 0; k < max_rank; k++) { old_prev[k] = prev[k]; old_post[k] = post[k]; prev[k] = -1; post[k] = -1; } for (k = 0; k < max_rank; k++) { if (pip_ord[k] != -1) { prev[pip_ord[k]] = old_prev[k]; post[pip_ord[k]] = old_post[k]; } } } if (mode) printf("WasPrev %2d= %2d %2d %2d\n", i, prev[0], prev[1], prev[2]); if (mode) printf("WasPost %2d= %2d %2d %2d\n", i, post[0], post[1], post[2]); if (mode) printf("ShdWid %2d= %2d %2d %2d\n", i, ShdWid[0], ShdWid[1], ShdWid[2]); if (ind_beg == -1) { ind_beg = i; time_beg = CurrProcTime(ind_beg); } /* for(k=0;k<4;k++) if(mm[k]==1) { for(j=3;j>k;j--) { prev[j]=prev[j-1]; post[j]=post[j-1]; } prev[k]=-1; post[k]=-1; } if(mode) printf("WillPrev %2d= %2d %2d %2d\n",i,prev[0],prev[1],prev[2]); if(mode) printf("WillPost %2d= %2d %2d %2d\n",i,post[0],post[1],post[2]); */ // printf("LZ=%f\n",call_time/LoopSZ*1000000); //printf("proc[%d] time=%f beg=%f cur_beg=%.f\n",i,CurrProcTime(i),time_beg,(CurrProcTime(i)-time_beg)*LoopSZ/call_time); // for(j=0;j 3)) { b[ord[k]] = invers[ord[k]] ? 2 : 1; beg = a_b(i); // время завершения вычисления блока 1 b[ord[k]] = invers[ord[k]] ? 1 : 2; step = a_b(i) - beg; // промежуток времени между временами завершения вычислений соседних блоков last = sz[b[0]][b[1]][b[2]][b[3]]; b[ord[k]] = invers[ord[k]] ? 0 : 3; // if(mode) printf("prev=%.f sz=%.f Beg %.f step=%.f * %d\n",last,a_b(i),beg,step,(bsize(i,ord[k],s[ord[k]])-2)); sz[b[0]][b[1]][b[2]][b[3]] = a_b(i); a_b(i) += beg + step * (bsize(i, ord[k], s[ord[k]]) - 2) - last; // расчет времени последнего блока в этом измерении cur = a_b(i); for (j = 0; j < rank_mas; j++) { //прогнозируем загрузку коммуникационных каналов comm[i][j] += (bsize(i, ord[k], s[ord[k]]) - 3)*prev_comm[ord[k]][j]; // printf("comm=== %.f increased by %.f\n",comm[i][j],(bsize(i,ord[k],s[ord[k]])-3)*prev_comm[ord[k]][j]); prev_comm[ord[k]][j] = 0; //чтобы повышать один раз } real_comm += (bsize(i, ord[k], s[ord[k]]) - 3)*last_real_comm; // printf("[last=%f] * %d = [real_comm=%f]\n",last_real_comm,bsize(i,ord[k],s[ord[k]])-3,real_comm); if (mode) printf("%d-%d-%d-%d-%d==%.f\n", i, b[0], b[1], b[2], b[3], a_b(i)); d = -1; break; //чтобы один раз вычислял этот блок } } //если был сделан ускоренный пробег, то не надо вычислять этот блок еще раз if (d < 0) continue; last_real_comm = 0; //comm - коммуникационый канал на вход и отвечает за то когда он закончит передачу данных for (k = 0; k < rank_mas; k++) { // if(mode) printf("Invers=%d Prev[%d]=%d b[k]=%d\n",invers[k],k,prev[k],b[k]); if (!invers[k] && b[k] == 0 && prev[k] != -1) { comm[i][k] = max(comm[i][k], a_change(prev[k], k, min(3, bsize(i, ord[k], s[ord[k]]) - 1))) + (TStart + (a_b(i) / min(s[k], msize(i, k))*ShdWid[k])*TByte)*LoopSZ / call_time; last_real_comm = max(last_real_comm, (TStart + (a_b(i) / min(s[k], msize(i, k))*ShdWid[k])*TByte)); } if (invers[k] && b[k] == min(3, bsize(i, ord[k], s[ord[k]]) - 1) && prev[k] != -1) { comm[i][k] = max(comm[i][k], a_change(prev[k], k, 0)) + (TStart + (a_b(i) / min(s[k], msize(i, k))*ShdWid[k])*TByte)*LoopSZ / call_time; last_real_comm = max(last_real_comm, (TStart + (a_b(i) / min(s[k], msize(i, k))*ShdWid[k])*TByte)); } //чтобы и отправитель ждал конца передачи данных надо сделать следующее if (invers[k] && b[k] == 0 && post[k] != -1 || !invers[k] && b[k] == min(3, bsize(i, ord[k], s[ord[k]]) - 1) && post[k] != -1) { last_real_comm = max(last_real_comm, (TStart + (0 * a_b(i) / min(s[k], msize(i, k))*ShdWid[k])*TByte)); } if (mode) printf("Proc[%d] last_real_comm=%f\n", i, last_real_comm); //у prev_comm есть направление [j] вдоль которого он ищет блоки с номерами 1 и 2 //для каждого направления он должен посмотреть, как изменялись коммуникационные каналы [k] for (j = 0; j < max_rank; j++) if (!invers[ord[j]] && b[ord[j]] == 1 || invers[ord[j]] && b[ord[j]] == 2) prev_comm[ord[j]][k] = comm[i][k]; for (j = 0; j < max_rank; j++) if (!invers[ord[j]] && b[ord[j]] == 2 || invers[ord[j]] && b[ord[j]] == 1) prev_comm[ord[j]][k] = comm[i][k] - prev_comm[ord[j]][k]; } for (k = 0; k < rank_mas; k++) { // printf("[k=%d] m=%.f comm=%.f\n",k,m,comm[i][k]); m = max(m, comm[i][k]); } mwait = m - mwait; com[i] += mwait * call_time / LoopSZ; real_comm += last_real_comm; //mwait и com[i] делают асинхронную передачу данных (совмещенную с вычислениями - и как результат учитывается только первая передача а остальные совмещаются) //last_real_comm и real_comm делает синхронную (не совмещенную с вычислениями - и как результат учитываются все передачи) // if(mwait>=0) printf("%d-%d-%d-%d wait[%d]=%.f [%f sec] last_real_comm=%f [sync=idle||insuf.sys]=%f\n",b[0],b[1],b[2],b[3],i,mwait,com[i],last_real_comm,com[i]-last_real_comm); if (add && com[i] > last_real_comm) { AddTime(__CPU_time_sys, i, com[i] - last_real_comm); AddTime(__Insuff_parall_sys, i, com[i] - last_real_comm); com[i] = last_real_comm; } sz[b[0]][b[1]][b[2]][b[3]] = a_b(i); a_b(i) += m; cur = a_b(i); if (mode) printf("%d-%d-%d-%d-%d=%.f\n", i, b[0], b[1], b[2], b[3], cur); if (mode) printf("Proc[%d] last_real_comm=%f\n", i, last_real_comm); } // printf("proc %d-%d-%d-%d done_time=%f\n",n[0],n[1],n[2],n[3],cur*call_time/LoopSZ); if (add) { // AddTime(__Synchronize,i,time_beg+cur*call_time/LoopSZ); // printf("proc[%d] wait_shad+= %f (async) || %f (sync)\n",i,com[i],real_comm); if (mode) printf("proc[%d] wait_shad+= %f\n", i, real_comm); // AddTime(__Wait_shadow,i,com[i]);//async AddTime(__Wait_shadow, i, real_comm);//sync // printf("wait[%d]=%f sec cur_beg=%.f cur=%.f raznica=%f\n",i,com[i],cur_beg,cur,(cur-cur_beg)*call_time/LoopSZ); // AddTime(__CPU_time_usr, i, (cur-cur_beg)*call_time/LoopSZ - com[i]); //call_time/(m*mult) } /* if(mode && com[i]>0.000001) { printf("proc(%d) wait %2.10f sec from [ ",i,com[i]); for(k=0;kGetRank()) for (n[0] = 0; n[0] < 4; n[0]++) for (n[1] = 0; n[1] < 4; n[1]++) for (n[2] = 0; n[2] < 4; n[2]++) free(a[i][n[0]][n[1]][n[2]]); for (i = 0; i < MPSProcCount(); i++) if (ProcBlock[i]->GetRank()) for (n[0] = 0; n[0] < 4; n[0]++) for (n[1] = 0; n[1] < 4; n[1]++) free(a[i][n[0]][n[1]]); for (i = 0; i < MPSProcCount(); i++) if (ProcBlock[i]->GetRank()) for (n[0] = 0; n[0] < 4; n[0]++) free(a[i][n[0]]); for (i = 0; i < MPSProcCount(); i++) if (ProcBlock[i]->GetRank()) free(a[i]); free(a); } for (i = 0; i < MPSProcCount(); i++) if (ProcBlock[i]->GetRank()) free(comm[i]); free(comm); //free(prev); //free(n); //free(b); //mode=0; return; } //==== procedure ========================================================================= void CommCost::Across(double call_timeArg, long LoopSZArg, LoopBlock** ProcBlockArg, int type_size) { int i, j, i0, k; int rank, r; vector dim; int ind[10]; vector pp; ProcBlock = ProcBlockArg; call_time = call_timeArg; LoopSZ = LoopSZArg; TStart = vm->getTStart(); TByte = vm->getTByte()*type_size; pp = vm->getSizeArray(); rank = pp.size(); // печать конфигурации процессорной решетки if (mode) { printf("VM %d", pp[0]); for (i = 1; i < rank; i++) printf("x%d", pp[i]); printf("\n"); } //calc invers for (i = 0; i < MPSProcCount(); i++) for (j = 0; j < ProcBlock[i]->GetRank(); j++) if (ProcBlock[i]->LSDim[j].Step < 0) { invers[j] = 1; ProcBlock[i]->LSDim[j].Step = -ProcBlock[i]->LSDim[j].Step; } else invers[j] = 0; // printf("Inverse %d %d %d\n",invers[0],invers[1],invers[2]); //calc rank_mas for (i = 0, rank_mas = 0; i < MPSProcCount(); i++) { r = ProcBlock[i]->GetRank(); if (rank_mas < r) rank_mas = r; } //correct rank if other dims equals 1 //xp for(i=k=rank_mas;irank_mas) { printf("Too many dimensions %d>%d\n",rank,rank_mas); exit(1);} if (rank_mas > max_rank) { printf("Cannot model ACROSS pipeline because of Array rank=%d>%d\n", rank_mas, max_rank); return; } s.resize(max_rank); p.resize(max_rank); dmax.resize(max_rank); dim.resize(max_rank); conv_beg.resize(max_rank); conv_end.resize(max_rank); mult_is.resize(max_rank); pip.resize(max_rank); ord.resize(max_rank); //s = (long *)malloc(max_rank * sizeof(long)); //p = (int *)malloc(max_rank * sizeof(int)); //dmax = (int *)malloc(max_rank * sizeof(int)); //dim = (int *)malloc(max_rank * sizeof(int)); //conv_beg = (int *)malloc(max_rank * sizeof(int)); //conv_end = (int *)malloc(max_rank * sizeof(int)); //mult_is = (int *)malloc(max_rank * sizeof(int)); //pip = (int *)malloc(max_rank * sizeof(int)); //ord = (int *)malloc(max_rank * sizeof(int)); for (i = rank; i < max_rank; i++) ShdWid[i] = 0; for (i = 0; i < rank; i++) ShdWid[i] = ShdWid(i); if (mode) printf("COMM ACROSS %5.10f ShdWid=%d %d %d %d\n", call_time, ShdWid[0], ShdWid[1], ShdWid[2], ShdWid[3]); for (k = 0; k < rank; k++) p[k] = pp[k]; //по другим измерения решетка процов имеет ширину 1 for (k = rank; k < max_rank; k++) p[k] = 1; //печать блоков каждого процессора if (mode) { for (i = 0; i < MPSProcCount(); i++) { r = ProcBlock[i]->GetRank(); for (k = 0; k < rank_mas; k++) ind[k] = i; //only comment i=ind[0]*p[2]*p[1]+ind[1]*p[2]+ind[2]; only comment for (k = rank_mas - 1; k >= 0; k--) { ind[k] = ind[k] % p[k]; for (x = 0; x < k; x++) ind[x] = ind[x] / p[k]; } printf("[%d", ind[0]); for (k = 1; k < max_rank; k++) if (k >= rank_mas) printf(",0"); else printf(",%d", ind[k]); printf("]%2d. ", i); for (j = 0; j < r; j++) printf("%d:%d:%d ", mbeg(i, j), mend(i, j), mstep(i, j)); printf("\n"); } } for (i = 0; i < max_rank; i++) { dmax[i] = 1; dim[i] = 1; } for (j = 0; j < MPSProcCount(); j++) if (ProcBlock[j]->GetRank()) break; first = j; //first proc with data //calc dmax(max_dim_size) for (k = 0; k < max_rank; k++) for (x = j, dmax[k] = msize(j, k), i = j + 1; i < MPSProcCount(); i++) if (ProcBlock[i]->GetRank() && (msize(i, k) > msize(x, k))) { x = i; dmax[k] = msize(i, k); } //calc mult (number of parallelizing pipelines) //эта часть помогает вычислить mult в дальнейшем if (rank_mas >= 2) { mult = 1; for (k = 0; k < max_rank; k++) mult_is[k] = 0; //only comment i=i0*p[2]*p[1]+j0*p[2]+e0; only comment for (i = 0; i < MPSProcCount(); i++) if (ProcBlock[i]->GetRank()) break; //i=first proc with data if (mode) { printf("p="); for (k = 0; k < rank_mas; k++) printf("%d ", p[k]); printf("\n"); } // Надо (x=0 i0=p[2]*p[1]) (x=1 i0=p[2]) (x=2 i0=1) // это смещения для вычисления соседних процов вдоль какого-то измерения for (x = 0; x < max_rank; x++) { for (k = x + 1, i0 = 1; k < rank_mas; k++) i0 = i0 * p[k]; if (p[x] > 1 && i + i0 < MPSProcCount()) { for (k = 0, r = 1; k < rank_mas; k++) if (mbeg(i + i0, k) != mbeg(i, k) || mend(i + i0, k) != mend(i, k)) { if (ShdWid[k] != 0) { r = 0; break; } else r = 2; } // r==0 (соседние процы по одному измерению имеют разные блоки) r==1 (одинаковые блоки) if (r) { mult *= p[x]; mult_is[x] = r; } } } } if (mode) printf("MULT %d %d %d %d = %d\n", mult_is[0], mult_is[1], mult_is[2], mult_is[3], mult); // for(i=0;iGetRank(); for (k = 0; k < r; k++) if (mbeg(i, k) != mbeg(j, k) || mend(i, k) != mend(j, k)) mm[k] = 0; } // for(i=0;i insuff.par.usr) mult_is == 2 (shdwid==0, => параллельные конвейеры) if (mode) printf("MULT %d %d %d %d\n", mult_is[0], mult_is[1], mult_is[2], mult_is[3]); //вычисляем какие процы участвуют в конвейере! (процы [от i1 до i2][от j1 до j2] ) i = first; //conv_beg[0,1,2] ~ i for (k = 0; k < max_rank; k++) conv_beg[k] = i; for (k = max_rank - 1; k >= 0; k--) { conv_beg[k] = conv_beg[k] % p[k]; for (x = 0; x < k; x++) conv_beg[x] = conv_beg[x] / p[k]; } for (k = 0; k < max_rank; k++) conv_end[k] = conv_beg[k]; for (x = 0; x < rank_mas; x++) { for (k = x + 1, i0 = 1; k < rank_mas; k++) i0 = i0 * p[k]; for (j = 1; j < p[x] && i + i0 < MPSProcCount() && ProcBlock[i + i0]->GetRank(); j++, i += i0) { for (k = 0, r = 1; k < rank_mas; k++) if (mbeg(i + i0, k) != mbeg(i, k) || mend(i + i0, k) != mend(i, k)) { r = 0; break; } // r==0 (соседние процы по одному измерению имеют разные блоки) r==1 (одинаковые блоки) if (r == 0) { conv_end[x]++; } } } ////вычисление процессоров по которым есть конвейер и заносится в массив 'pip' for (i = 0; i < max_rank; i++) pip[i] = conv_end[i] - conv_beg[i] + 1; if (mode) printf("Konv procs=%d %d %d %d\n", pip[0], pip[1], pip[2], pip[3]); if (mode) { printf("We got %d KONV ", mult); for (k = 0; k < max_rank; k++) if (k >= rank_mas) printf("%d=%d ", conv_beg[k], conv_end[k]); else printf("%d:%d ", conv_beg[k], conv_end[k]); printf("\n"); } //вычисляем размеры массива который надо выполнить в конвейере //only comment i=ind[0]*p[2]*p[1]+ind[1]*p[2]+ind[2]; only comment for (k = 0; k < max_rank; k++) { for (x = k + 1, y = 1; x < max_rank; x++) y *= p[x]; dim[k] = mend(conv_end[k] * y, k) - mbeg(conv_beg[k] * y, k) + 1; } if (mode) printf("Dim %d %d %d %d\n", dim[0], dim[1], dim[2], dim[3]); //!!!!!!!!!!! пока еще не рассмотрен случай когда rank>3 // и когда есть >=2 параллельных конвейера (одинаковые) //подсчет времени коммуникаций и времени работы процов if (rank_mas == 1) //одномерный массив, => нет конвейера { if (mode) printf("No pipeline\n"); double a, b, c, d; k = 0; a = call_time; b = (p[0] - 1)*(TStart + ShdWid[0] * TByte); if (mode) printf("exec=%f comm=%f\n", a, b); for (i = 1; i < p[0]; i++) //не учтено что порядок может быть обратным { if (i != 1) c = CurrInterval->GetProcPred(i - 1, _Execution_time); else c = 0.0; d = CurrInterval->GetProcPred(i, _Execution_time); // AddTime(__Insuff_parall_usr, currentVM->map(i), i*call_time/p[0]); //убрал, потому что нет дублирований, есть разбалансировка AddTime(__Wait_shadow, currentVM->map(i), (TStart + ShdWid[0] * TByte) + max(0, c - d)); } for (i = 0; i < p[0]; i++) { AddTime(__CPU_time_usr, currentVM->map(i), call_time / p[0]); } } else { //pipeline in old dvm long M, N, P, W, Q; double DD, shad; // M-конвейеризуемые N-НЕконв.(квантуемые) P-кол-во процов для конвейера for (i = 0, M = 1, N = 1, P = 1; i < rank_mas; i++) { if (mm[i] || ShdWid[i] == 0) N *= dim[i]; else { M *= dim[i]; P *= pip[rank - 1 - i]; } } for (i = 0, DD = 1; i < rank_mas; i++) DD *= dmax[i]; for (i = 0, W = 0, shad = 0; i < rank_mas; i++) if (mm[i] == 0) shad += DD / dmax[i] * ShdWid[i]; // есть конвейер по этому измерению W = ceil(shad / N); if (mode) printf("M=%d N=%d W=%d P=%d\n", M, N, W, P); if (mode) printf("W=%d (Shad=%5.0f)\n", W, shad); double Tc = call_time / LoopSZ; // double Tm=0.000023/500; // double T0wrecv=0.000001; // double Tirecv=0.000001; // double Tisend=0.000001; double Tm = TStart + TByte; double T0wrecv = TStart; double Tirecv = TStart; double Tisend = TStart; double tt1, tt2; if (mode) { //printf("pip=%d %d %d \n",pip[0],pip[1],pip[2]); if (W*Tm > 0.0000000001) printf("Greater? P=%d or %7.0f\n", P, (M*Tc) / (W*Tm)); } if (W*Tm > 0.0000000001 && P > (M*Tc) / (W*Tm)) { if (TStart > 0) { int tmp1 = N*(P*(Tc*M + P * Tm*W) - 2 * Tc*M); int tmp2 = (P*(Tirecv + T0wrecv)); Q = sqrt(N*(P*(Tc*M + P * Tm*W) - 2 * Tc*M) / (P*(Tirecv + T0wrecv))); } else Q = -1; if (Q > N) Q = N; if (Q < 1) Q = 1; // tt1 = (Tirecv + T0wrecv)*Q + (N*( P*(Tc*M + P*Tm*W) - 2*Tc*M ) / P )/Q; // tt2 = Tirecv*P + Tisend*(P - 1) + T0wrecv + N*Tm*W; tt1 = (N * (P - 2) * Tc * M) / (P * Q); tt2 = Tirecv * P + Tisend * (P - 1) + T0wrecv + (Tirecv + T0wrecv) * Q + N * Tm * W + N * P * Tm * W / Q; } else { if (TStart > 0) Q = sqrt(N*(P - 1)*(M*Tc + P * Tm*W) / (P*(Tirecv + T0wrecv))); else Q = -1; if (Q > N) Q = N; if (Q < 1) Q = 1; // tt1 = (Tirecv + T0wrecv)*Q + (N*(P - 1)*(Tc*M + P*Tm*W)/P)/Q; // tt2 = Tirecv*P + Tisend*(P - 1) + T0wrecv + Tc*M*N/P; tt1 = (N*(P - 1)*Tc*M) / (P*Q) + Tc * M*N / P; tt2 = Tirecv * P + Tisend * (P - 1) + T0wrecv + (Tirecv + T0wrecv)*Q + N * (P - 1)*Tm*W / Q; } if (mode) printf("Q=%d time=%5.10f+%5.10f=%5.10f\n", Q, tt1, tt2, tt1 + tt2); // { // long *kk; // kk=(long*)malloc(max_rank*sizeof(long)); for (i = 0; i < rank_mas; i++) s[i] = dmax[i]; for (i = rank_mas; i < max_rank; i++) s[i] = 1; // Квантуем по многим измерениям for (i = 0, N = min(Q, N); i < rank_mas; i++) if (mm[i] || ShdWid[i] == 0) { if (N >= dim[i]) { s[i] = 1; if (mode) printf("QQ=%d ", dim[i]); } else { s[i] = dim[i] / N; if (mode) printf("QQ=%d ", N); break; } N /= dim[i]; } // x=kk[0]; y=kk[1]; z=kk[2]; // free(kk); // } // printf("Shd=%d %d %d\n",ShdWid[0],ShdWid[1],ShdWid[2]); if (mode) printf("Konv Steps [%d,%d,%d,%d]\n", s[0], s[1], s[2], s[3]); // x=dmax[0];y=1;z=242; for (k = 0; k < max_rank; k++) // standart order of doing cycles ord[k] = k; if (full_mode == 0) add = 1; //записывает времена в интервал calculate_all_pipes(); if (mode) printf("Time_c=%5.10f time_x=%5.10f\n", time_c, time_x); //end of pipeline in old dvm if (full_mode) // full_mode - searching better than pipe in old dvm { double ttt = 1000000000; long *best, *ord_best, count, *st;//st=step in full_search best = (long *)malloc(max_rank * sizeof(long)); ord_best = (long *)malloc(max_rank * sizeof(long)); st = (long *)malloc(max_rank * sizeof(long)); add = 0; // не записывает в интервал, а только ищет наилучший // if(full_mode==2) for(i=1;i= 2) //full_search { // printf("Step %d %d %d %d\n",st[0],st[1],st[2],st[3]); for (s[0] = 1; s[0] < dmax[ord[0]] || s[0] < dmax[ord[0]] + st[0] && (s[0] = dmax[ord[0]]); s[0] += st[0]) for (s[1] = 1; s[1] < dmax[ord[1]] || s[1] < dmax[ord[1]] + st[1] && (s[1] = dmax[ord[1]]); s[1] += st[1]) for (s[2] = 1; s[2] < dmax[ord[2]] || s[2] < dmax[ord[2]] + st[2] && (s[2] = dmax[ord[2]]); s[2] += st[2]) for (s[3] = 1; s[3] < dmax[ord[3]] || s[3] < dmax[ord[3]] + st[3] && (s[3] = dmax[ord[3]]); s[3] += st[3]) { calculate_all_pipes(); if (time_x < ttt) { ttt = time_x; for (k = 0; k < max_rank; k++) { best[ord[k]] = s[k]; ord_best[k] = ord[k]; } if (mode) printf("BETTER %d %d %d %d [comm=%.10f] time=%.10f\n", s[ord[0]], s[ord[1]], s[ord[2]], s[ord[3]], time_c, time_x); } count++; } } if (full_mode == 1) { ord[0] = ord[1] = ord[2] = ord[3] = max_rank; } } for (k = 0; k < max_rank; k++) { ord[k] = ord_best[k]; s[k] = best[ord[k]]; } if (mode) printf("BEST[%d %d %d %d] %d %d %d %d = %5.10f [tried %d variants]\n", ord[0], ord[1], ord[2], ord[3], s[0], s[1], s[2], s[3], ttt, count); add = 1; //запись в интервал calculate_all_pipes(); } } //free(pip); //free(mult_is); //free(dmax); //free(conv_beg); //free(conv_end); //free(s); return; } //=************************************************************************************** void CommCost::BoundUpdate(DArray *daPtr, vector & dimInfo, bool IsCorner) { long p1, p2; long bound_size, coner_size; Block b; long sizeNoConerDim; for (p1 = 0; p1 < vm->GetLSize(); p1++) { // Блок массива daPtr, распределенный на процессор p1 //grig b = Block(daPtr, p1); b = Block(daPtr, p1,1); //\grig if (b.empty()) continue; vector::iterator first = dimInfo.begin(); vector::iterator last = dimInfo.end(); // определение требуемых пересылок для правой и левой границы while (first != last) { if (b.IsLeft(first->arrDim, 0)) { // есть сосед слева if (first->RightBSize > 0) { bound_size = b.GetBlockSizeMult(first->arrDim) * first->RightBSize; p2 = vm->GetSpecLI(p1, first->vmDim, - first->dir); // += так как Update if(p2>=0 && p2GetLSize()) //====// transfer[vm->map(p1)][vm->map(p2)] += bound_size * daPtr->TypeSize; } } if (b.IsRight(first->arrDim, daPtr->GetSize(first->arrDim) - 1)) { // есть сосед справа if (first->LeftBSize >0) { bound_size = b.GetBlockSizeMult(first->arrDim) * first->LeftBSize; p2 = vm->GetSpecLI(p1, first->vmDim, first->dir); if(p2>=0 && p2GetLSize()) //====// transfer[vm->map(p1)][vm->map(p2)] += bound_size * daPtr->TypeSize; } } first++; } // определение необходимых пересылок "угловых" элементов // Внимание (только для 2-х мерного случая)!!! // Случай включения в границы массива "угловых" элементов // рассмотрен в 2-х мерном варианте(> 2 пока не учитываю) if (IsCorner) { sizeNoConerDim = b.GetBlockSizeMult2(dimInfo[0].arrDim, dimInfo[1].arrDim); if (b.IsLeft(dimInfo[0].arrDim, 0) && b.IsLeft(dimInfo[1].arrDim, 0)) { if (dimInfo[0].RightBSize > 0 && dimInfo[1].RightBSize > 0) { coner_size = sizeNoConerDim * dimInfo[0].RightBSize * dimInfo[1].RightBSize; p2 = vm->GetSpecLI(p1, dimInfo[0].vmDim, - dimInfo[0].dir); p2 = vm->GetSpecLI(p2, dimInfo[1].vmDim, - dimInfo[1].dir); transfer[vm->map(p1)][vm->map(p2)] += coner_size * daPtr ->TypeSize; } } if (b.IsLeft(dimInfo[0].arrDim, 0) && b.IsRight(dimInfo[1].arrDim, daPtr->GetSize(dimInfo[1].arrDim) - 1)) { if (dimInfo[0].RightBSize > 0 && dimInfo[1].LeftBSize > 0) { coner_size = sizeNoConerDim * dimInfo[0].RightBSize * dimInfo[1].LeftBSize; p2 = vm->GetSpecLI(p1, dimInfo[0].vmDim, - dimInfo[0].dir); p2 = vm->GetSpecLI(p2, dimInfo[1].vmDim, dimInfo[1].dir); transfer[vm->map(p1)][vm->map(p2)] += coner_size * daPtr ->TypeSize; } } if (b.IsRight(dimInfo[0].arrDim, daPtr->GetSize(dimInfo[0].arrDim) - 1) && b.IsLeft(dimInfo[1].arrDim, 0)) { if (dimInfo[0].LeftBSize > 0 && dimInfo[1].RightBSize > 0) { coner_size = sizeNoConerDim * dimInfo[0].LeftBSize * dimInfo[1].RightBSize; p2 = vm->GetSpecLI(p1, dimInfo[0].vmDim, dimInfo[0].dir); p2 = vm->GetSpecLI(p2, dimInfo[1].vmDim, - dimInfo[1].dir); transfer[vm->map(p1)][vm->map(p2)] += coner_size * daPtr ->TypeSize; } } if (b.IsRight(dimInfo[0].arrDim, daPtr->GetSize(dimInfo[0].arrDim) - 1) && b.IsRight(dimInfo[1].arrDim, daPtr->GetSize(dimInfo[1].arrDim) - 1)) { if (dimInfo[0].LeftBSize > 0 && dimInfo[1].LeftBSize > 0) { coner_size = sizeNoConerDim * dimInfo[0].LeftBSize * dimInfo[1].LeftBSize; p2 = vm->GetSpecLI(p1, dimInfo[0].vmDim, dimInfo[0].dir); p2 = vm->GetSpecLI(p2, dimInfo[1].vmDim, dimInfo[1].dir); transfer[vm->map(p1)][vm->map(p2)] += coner_size * daPtr ->TypeSize; } } } } // prot << endl; #ifdef _TIME_TRACE_ // потом убрать prot << "CommCost::BoundUpdate: transfer" << endl; long pp1, pp2; for (pp1 = 0; pp1 < rootVM->GetLSize(); pp1++) { for (pp2 = 0; pp2 < rootVM->GetLSize(); pp2++) { if (transfer[pp1][pp2] != 0) prot << '[' << pp1 << ',' << pp2 << "] = " << transfer[pp1][pp2] << "; "; } prot << endl; } // потом убрать #endif } void CommCost::CopyUpdate(DArray * FromArray, Block & readBlock) { long p1, p2, size; //==== if(mode) printf("My CopyUpdate\n"); //=*** for (p1 = 0; p1 < vm->GetLSize(); p1++) { Block locBlock(FromArray, p1,1); //printf("LocBlock^readBlock: "); Block bi = locBlock ^ readBlock; //printf("Loc^readDone\n "); //printf("loc[%d].0=%d-%d\n",p1,locBlock.GetLower(0),locBlock.GetUpper(0)); //printf("loc[%d].1=%d-%d\n",p1,locBlock.GetLower(1),locBlock.GetUpper(1)); //printf("read.0=%d-%d\n",readBlock.GetLower(0),readBlock.GetUpper(0)); //printf("read.1=%d-%d\n",readBlock.GetLower(1),readBlock.GetUpper(1)); //printf("bi.0=%d-%d\n",bi.GetLower(0),bi.GetUpper(0)); //printf("bi.1=%d-%d\n",bi.GetLower(1),bi.GetUpper(1)); //printf("*********************************************\n"); // printf("locBlock=%x, readBlock=%x, bi=%x\n", &locBlock, &readBlock, &bi); if (!locBlock.empty() && !bi.empty()) { // можно оставить только последнее условие // локальная часть читаемого массива не пуста size = bi.GetBlockSize(); for (p2 = 0; p2 < vm->GetLSize(); p2++) { if (p1 != p2) { Block locBlock1(FromArray, p2,1); // printf("locBlock1=%x\n", &locBlock1); //printf("LocBlock1^bi: "); if (locBlock1.empty() || (locBlock1 ^ bi).empty()) { // последнее условие можно только оставить // нет этой части читаемого массива на данном процессоре transfer[p1][p2] += size * FromArray->TypeSize; // update if(mode) printf("Transfer[%d][%d]+=%d*%d\n",p1,p2,FromArray->TypeSize,size); } } } } p2 = p1; } } //==== void CommCost::CopyUpdateDistr(DArray * FromArray, Block &readBlock, long p1) { long size, p2; if(mode) printf("***My CopyUpdateDistr***\n"); /* for (p2=0; p2 < vm->GetLSize(); p2++) { Block locBlock1(FromArray, p2,1); if(mode) printf("Proc[%d]=%d-%d %d-%d\n",p2,locBlock1.GetLower(0),locBlock1.GetUpper(0),locBlock1.GetLower(1),locBlock1.GetUpper(1)); // if(mode) printf("Proc[%d]=%d-%d %d-%d\n",p2,locBlock1.GetLower(0),locBlock1.GetUpper(0),locBlock1.GetLower(1),locBlock1.GetUpper(1),locBlock1.GetLower(2),locBlock1.GetUpper(2)); } */ for (p2=0; p2 < vm->GetLSize(); p2++) { if (p1 != p2) { Block locBlock1(FromArray, p2,1); //printf("loc[%d].0=%d-%d\n",p2,locBlock1.GetLower(0),locBlock1.GetUpper(0)); //printf("loc[%d].1=%d-%d\n",p2,locBlock1.GetLower(1),locBlock1.GetUpper(1)); //printf("read[%d].0=%d-%d\n",p2,readBlock.GetLower(0),readBlock.GetUpper(0)); //printf("read[%d].1=%d-%d\n",p2,readBlock.GetLower(1),readBlock.GetUpper(1)); Block bi2 = locBlock1 ^ readBlock; size = bi2.GetBlockSize(); if (!bi2.empty()) { //printf("bi2.0=%d-%d\n",bi2.GetLower(0),bi2.GetUpper(0)); //printf("bi2.1=%d-%d\n",bi2.GetLower(1),bi2.GetUpper(1)); //printf("*********************************************\n"); transfer[p1][p2] += size* FromArray->TypeSize; if(mode) printf("Transfer[%d][%d]+=%d*%d\n",p1,p2,FromArray->TypeSize,size); } //else // printf("bi2.EMPTY\n*********************************************\n"); } } } long CommCost::GetLSize() { return vm->GetLSize(); } //=***