/** Read a string array from socket */ int streadstrarr(int sfd, char ***str, int *nstr){ int ans=streadint(sfd, nstr); if(ans) return ans; *str=calloc(*nstr, sizeof(char*)); for(int istr=0; istr<*nstr && !ans; istr++){ ans=streadstr(sfd, &(*str)[istr]); } return ans; }
/** Read a string from socket */ int streadstr(int sfd, char **str){ int len; int ans=streadint(sfd, &len); if(!ans && len>0){ *str=calloc(1, sizeof(char)*len); ans=stread(sfd, *str, len); if(ans){ free(*str); *str=NULL; } }else{ *str=NULL; } return ans; }
static void maos_server(PARMS_T *parms){ if(maos_server_fd<0){ error("Invalid maos_server_fd\n"); EXIT; } warning("maos running in server mode\n"); int msglen; int sock=maos_server_fd; while(!streadint(sock, &msglen)){ int ret=0;/*acknowledgement of the command. 0: accepted. otherwise: not understood*/ int *msg=alloca(sizeof(int)*msglen); if(streadintarr(sock, msg, msglen)){ break; } switch(msg[0]){ case MAOS_ASSIGN_WFS:{/*Specifies which WFS to be handled*/ for(int iwfs=0; iwfs<parms->nwfs; iwfs++){ parms->wfs[iwfs].sock=msg[iwfs+1]?-1:0; } }break; case MAOS_ASSIGN_EVL:{/*Specifies which EVL to be handled*/ if(!parms->evl.sock){ parms->evl.sock=calloc(parms->evl.nevl, sizeof(int)); } for(int ievl=0; ievl<parms->evl.nevl; ievl++){ parms->evl.sock->p[ievl]=msg[ievl+1]?-1:0; } }break; case MAOS_ASSIGN_RECON:{/*Specifies whether recon should be handled*/ parms->recon.sock=msg[1]?-1:0; }break; case MAOS_ASSIGN_DONE:{/*Now start configuration*/ error("Not completed\n"); }break; default: ret=1; }/*switch*/ if(stwriteint(sock, ret)){ break; } } warning("maos_server exited\n"); //todo:listening on socket for commands. //maos client mode: start maos server mode via scheduler. }
int main(int argc, char *argv[]){ enum{ P_EXE, P_FRAC, P_NSTEP, P_TOT, }; if(argc!=P_TOT){ info2("Usage: \n\tenv MVM_CLIENT=hostname MVM_PORT=port MVM_SASTEP=sastep ./mvm_cpu fraction nstep\n"); _Exit(0); } int fraction=strtol(argv[P_FRAC], NULL, 10); int nstep=strtol(argv[P_NSTEP], NULL, 10); int nstep0=nstep>1?20:0;//warm up dmat *d_saind=dread("NFIRAOS_saind"); const int nsa=(d_saind->nx-1)/fraction; int *saind=mymalloc((1+nsa),int); for(int i=0; i<nsa+1; i++){ saind[i]=(int)d_saind->p[i]; } dfree(d_saind); const int totpix=saind[nsa]; const int nact=6981;//active subapertures. int ng=nsa*2; float FSMdelta=-0.2; smat *dm=snew(nact,1); smat *mvm=snew(nact, ng); smat *mtch=snew(totpix*2,1); smat *grad=snew(ng,1); smat *im0=snew(totpix,3); short *pix=mymalloc(totpix,short); short *pixbias=mymalloc(totpix,short); { rand_t rseed; seed_rand(&rseed, 1); srandu(mvm, 1e-7, &rseed); srandu(mtch, 1, &rseed); for(int i=0; i<totpix; i++){ pix[i]=(short)(randu(&rseed)*25565); pixbias[i]=(short)(randu(&rseed)*1000); } } smat *mvmt=strans(mvm); int sastep=200;//how many subapertures each time int nrep=1; if(getenv("MVM_NREP")){ nrep=strtol(getenv("MVM_NREP"), NULL, 10); } if(getenv("MVM_SECT")){ sastep=nsa/strtol(getenv("MVM_SECT"), NULL, 10); } if(getenv("MVM_TRANS")){ use_trans=strtol(getenv("MVM_TRANS"), NULL, 10); } if(getenv("MVM_SASTEP")){ sastep=strtol(getenv("MVM_SASTEP"), NULL, 10); } info2("use_trans=%d, nrep=%d, sastep=%d\n", use_trans, nrep, sastep); int sock=-1; char* MVM_CLIENT=getenv("MVM_CLIENT"); if(MVM_CLIENT){ short port=(short)strtol(getenv("MVM_PORT"), NULL, 10); sock=connect_port(MVM_CLIENT, port, 0 ,1); if(sock!=-1) { info2("Connected\n"); int cmd[7]; cmd[0]=nact; cmd[1]=nsa; cmd[2]=sastep; cmd[3]=totpix; cmd[4]=nstep; cmd[5]=nstep0; cmd[6]=2; if(stwriteintarr(sock, cmd, 7) || stwriteintarr(sock, saind, nsa+1) || stwrite(sock, pix, sizeof(short)*totpix)){ close(sock); sock=-1; warning("Failed: %s\n", strerror(errno)); } } } int ready=0; if(sock!=-1 && stwriteint(sock, ready)){ warning("error send ready signal: %s\n", strerror(errno)); close(sock); sock=-1; } smat *timing=snew(nstep, 1); TIC; float timtot=0, timmax=0, timmin=INFINITY; set_realtime(-1, -20); for(int jstep=-nstep0; jstep<nstep; jstep++){ int istep=jstep<0?0:jstep; tic; double theta=M_PI*0.5*istep+FSMdelta; float cd=cos(theta); float sd=cos(theta); szero(dm); for(int isa=0; isa<nsa; isa+=sastep){ int npixleft; int nsaleft; if(nsa<isa+sastep){//terminate npixleft=totpix-saind[isa]; nsaleft=nsa-isa; }else{ npixleft=saind[isa+sastep]-saind[isa]; nsaleft=sastep; } short *pcur=pix+saind[isa]; if(sock!=-1){ if(stread(sock, pcur, sizeof(short)*npixleft)){ warning("failed: %s\n", strerror(errno)); close(sock); sock=-1; _Exit(1); } if(isa==0) tic; } //Matched filter mtch_do(mtch->p, pix, pixbias, grad->p+isa*2, im0->p, im0->p+totpix, im0->p+totpix*2, saind+isa, nsaleft, cd, sd); //MVM for(int irep=0; irep<nrep; irep++){ if(use_trans){ mvmt_do(mvmt->p+isa*2, grad->p+isa*2,dm->p, nact, nsaleft*2, ng); }else{ mvm_do(mvm->p+isa*2*nact, grad->p+isa*2, dm->p, nact, nsaleft*2); } } }//for isa if(sock!=-1){ if(stwrite(sock, dm->p, sizeof(float)*nact)){ warning("error write dmres: %s\n", strerror(errno)); close(sock); sock=-1; _Exit(1); } if(streadint(sock, &ready)){//acknowledgement. warning("error read ack failed: %s\n", strerror(errno)); close(sock), sock=-1; _Exit(1); } timing->p[istep]=ready*1.e-6; }else{ timing->p[istep]=toc3;//do not tic. } if(jstep==istep){ timtot+=timing->p[istep]; if(timmax<timing->p[istep]){ timmax=timing->p[istep]; } if(timmin>timing->p[istep]){ timmin=timing->p[istep]; } } }//for istep float timmean=timtot/nstep; info2("Timing is mean %.3f, max %.3f min %.3f. BW is %.1f of 51.2GB/s\n", timmean*1e3, timmax*1e3, timmin*1e3, nrep*(nact*ng+nact+ng)*sizeof(float)/timmean/(1024*1024*1024)); writebin(timing, "cpu_timing_%s", HOST); if(nstep==1){ writearr("cpu_pix", 1, sizeof(short), M_INT16, NULL, pix, totpix, 1); writearr("cpu_pixbias", 1, sizeof(short), M_INT16, NULL, pixbias, totpix, 1); writebin(dm, "cpu_dm"); writebin(grad, "cpu_grad"); writebin(mvm, "cpu_mvm"); writebin(mtch, "cpu_mtch"); } }
//server for mvmfull_real int mvm_server(int sock){ int cmd[7]; if(streadintarr(sock, cmd, 7)){ return -1; } int nact=cmd[0]; int nsa=cmd[1]; int sastep=cmd[2]; int totpix=cmd[3]; int pixpsa=totpix; int nstep=cmd[4]; int nstep0=cmd[5]; int type=cmd[6]; dbg("type=%d, nact=%d, nsa=%d, sastep=%d, %s=%d, nstep=%d\n",type, nact, nsa, sastep, type==1?"pixpsa":"totpix", totpix, nstep); int *saind=NULL; if(type==1){//mvmfull_iwfs totpix=pixpsa*nsa; }else{//mvmfull_real saind=mymalloc((nsa+1),int); if(streadintarr(sock, saind, nsa+1)){ return -1; } } short *pix=mymalloc(totpix,short); if(type==1){ rand_t rseed; seed_rand(&rseed, 1); for(int i=0; i<totpix; i++){ pix[i]=(short)randu(&rseed); } }else{ if(stread(sock, pix, totpix*sizeof(short))){ return -1; } } smat *dmres=snew(nact, 1); int ready; streadint(sock, &ready); //wait for client to be ready. #if __linux__ struct timespec ct; clock_gettime(CLOCK_MONOTONIC, &ct); int readtime_ns=500000;//500 micro-second read out time. int frametime_ns=1250000;//frame time. int nsend=((nsa+sastep-1)/sastep);//number of segments sent along read out int int1_ns=readtime_ns/nsend;//interval between segment sending int int2_ns=frametime_ns-readtime_ns;//interval after last segment. #endif TIC;tic; for(int istep=-nstep0; istep<nstep; istep++){ //info("\rSend trigger "); #if __linux__ //scheduled start time of the frame. double tk0=(double)ct.tv_sec+(double)ct.tv_nsec*1.e-9; #else tic; #endif for(int isa=0; isa<nsa; isa+=sastep){ #if __linux__ if(clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &ct, NULL)){ warning("clock_nanosleep is interrupted\n"); } if(isa==0){ tic; } #endif int nleft; if(type==1){ nleft=((nsa-isa)<sastep?(nsa-isa):sastep)*pixpsa; }else{ if(nsa<isa+sastep){//terminate nleft=totpix-saind[isa]; }else{ nleft=saind[isa+sastep]-saind[isa]; } } if(stwrite(sock, pix+(type==1?pixpsa*isa:saind[isa]), 2*nleft)){//2 byte data. warning("failed: %s\n", strerror(errno)); return -1; } #if __linux__ ct.tv_nsec+=int1_ns; while(ct.tv_nsec>=1000000000){ ct.tv_nsec-=1000000000; ct.tv_sec++; } #endif } if(stread(sock, dmres->p, sizeof(float)*nact)){ warning("read dmres failed: %s\n", strerror(errno)); return -1; } ready=(int)(toc3*1e6);//mvm is finished. #if __linux__ if(nstep<100){ dbg("tk=%.6f tic=%.6f, toc=%.6f, ready=%.6f\n", tk0, tk, myclockd(), ready*1e-6); } #endif if(stwriteint(sock, ready)){ warning("write ready failed: %s\n", strerror(errno)); return -1; } //set next frame start time. #if __linux__ ct.tv_nsec+=int2_ns; while(ct.tv_nsec>=1000000000){ ct.tv_nsec-=1000000000; ct.tv_sec++; } #endif if((istep & 0xFF) == 0xFF){ info("%d %d us.\n", istep, ready); } } info("\n"); return -1; }