/* TODO update description */ int PHS(void *out, size_t outlen, const void *in, size_t inlen, const void *salt, size_t saltlen, unsigned int t_cost, unsigned int m_cost) { phs_ctx_t ctx; /* *********** initialization steps *********** */ // derive state size from somewhere ctx.state_bytes = pow(2, m_cost+8); /* we use at least 256 byte as the state */ ctx.state_words = ctx.state_bytes >> 2; /* we operate on 32-bit words */ ctx.inner_rounds = m_cost >> 4; /* number of times the whole state is overwritten */ if (ctx.inner_rounds < 2) { /* use at least two inner rounds! */ ctx.inner_rounds = 2; } ctx.outer_rounds = t_cost; /* number of times we rehash */ if (ctx.outer_rounds == 0) { /* use at least one outer round! */ ctx.outer_rounds = 1; } /* allocate memory for the full state (32-bit counter + state) and rehashing */ Dprintf("DEBUG: Allocating %"PRIu64" bytes of memory for prefixed state buffer...\n", (ctx.state_words + 1) * sizeof(uint32_t)); ctx.stateprefix = (uint32_t *) calloc(ctx.state_words + 1, sizeof(uint32_t)); Dprintf("DEBUG: Allocating %"PRIu64" bytes of memory for rehashing buffer...\n", ((PHS_REHASH_SIZE/4) + 1) * sizeof(uint32_t)); ctx.rehashprefix = (uint32_t *) calloc((PHS_REHASH_SIZE/4), sizeof(uint32_t)); /* set the ctx.state and ctx.rehash pointers to the non-prefixed buffer */ ctx.state = ctx.stateprefix + 1; ctx.rehash = ctx.rehashprefix + 1; /* initialize state from pw and salt */ Dprintf("DEBUG: initializing state with password and salt...\n"); phs_init(&ctx, salt, in, inlen); /* **** end of initialization **** */ Dprintf("Info : we could wipe the pw and salt now...\n"); /* *********** Begin DEBUG-only statistics *********** */ #ifdef PHC_DEBUG_STATISTICS /* allocate space and clear counter values */ for (int i = 0; i < PHS_F_COUNT; i++) { cnt_idx[i] = 0; } /* allocate and clear memory for address counters */ cnt_tgt_addr = (uint64_t*) calloc(ctx.state_words, sizeof(uint64_t)); #endif /* *********** End DEBUG-only statistics *********** */ /* *********** time wasting computation steps *********** */ for (uint32_t i = 0; i < ctx.outer_rounds; i++) { Dprintf("DEBUG: executing outer round: %" PRIu32 " \n", i); /* perform multiple calls to function F and scramble the bits in the state */ phs_upd_state(&ctx); /* re-distribute entropy */ phs_upd_entropy(&ctx); } /* generate 'outlen' bytes of output and store it in 'out' */ phs_gen_output(&ctx, outlen, out); /* Clean up the memory we allocated */ Dprintf("DEBUG: freeing state...\n"); free(ctx.stateprefix); Dprintf("DEBUG: freeing rehash...\n"); free(ctx.rehashprefix); /* *********** Begin DEBUG-only statistics *********** */ #ifdef PHC_DEBUG_STATISTICS printf("********* Statistics **********\n"); double rounds = ctx.inner_rounds * ctx.state_words * ctx.outer_rounds; printf("Function calls:\n"); for (int i = 0; i < PHS_F_COUNT; i++) { double usage = (cnt_idx[i] / rounds) * 100; printf("F[%d]: %07.4lf%% (%" PRIu64 ")\n", i, usage, cnt_idx[i]); } printf("State usage as [tgt] addresses: \n"); for (int i = 0; i < ctx.state_words; i++) { double tgt_usage = (cnt_tgt_addr[i] / rounds) * 100; printf("[%08.6lf%%] ", tgt_usage); if (i % 8 == 7) { printf("\n"); } } printf("Memory used: %" PRIu32 " byte, functions called: %0.0lf\n", ctx.state_bytes, rounds); free(cnt_tgt_addr); #endif /* *********** End DEBUG-only statistics *********** */ return 0; }
//--------------------------------------------------------------------------- // mpi_slaving: //--------------------------------------------------------------------------- int mpi_slaving() { // Declare local variables MPI_Datatype MPI_SLAVEINF; /* Dataype for MPI communications */ slaveinfo sl_info; /* Information structure for slaves */ MPI_Status *status; /* Recv status handler */ int used_size; /* # of processors used */ long sfN; /* # of pixels in subfield */ float *data = NULL; /* subfield data burst */ float *winH = NULL; /* apodisation window for SR calc. */ float *winF = NULL; /* apodisation window for phase rec. */ float *mask = NULL; /* DiffLim Mask */ float *pc = NULL; /* Phase Consistency */ /* for reallocation: needs to be NULL */ int *shifts = NULL; /* shifts for KT Cross Spectra */ /* for reallocation: needs to be NULL */ int maxk; /* number of shifts */ // Triple correlation part long *index = NULL; /* index list for bispectrum vectors */ long bs_cnt; /* # of vectors used */ float *bsc = NULL; /* complex non-red/red bispectrum */ float *wc = NULL; /* complex non-red/red bs weights */ float *p1 = NULL; /* phase matrix for iterativ reconstr. */ float *aphs = NULL; /* average of low frequencies */ // General part float *phs = NULL; /* Phase of reconstructed image */ float *amp = NULL; /* Amplitude of reconstructed image */ int c = GO; /* helpers */ long i; // set up status variable for sends and receives status = (MPI_Status *) malloc(sizeof(MPI_Status)); // Set Slaveinfo datatype for MPI sends and receives mpi_setslavetype(&MPI_SLAVEINF); // Receive number of jobs ... MPI_Bcast(&used_size, 1, MPI_INT, 0, MPI_COMM_WORLD); // ...and if used_size = NOGO, we are quitting the slave! if (used_size == NOGO) { // free memory MPI_Type_free(&MPI_SLAVEINF); free(status); // returning NOGO quits the slaves in entry.c return NOGO; } // ...and decide if I am needed if (used_size > proc_id) { // work until TAG says NOGO while (GO) { // Receive the data information MPI_Recv(&sl_info, 1, MPI_SLAVEINF, 0, MPI_ANY_TAG, MPI_COMM_WORLD, status); // Break if shutdown signal was sent if (status->MPI_TAG == NOGO) break; if (status->MPI_TAG == TC) { /* First time allocation of memory */ if (c) { // find number of pixels in subfield sfN = sl_info.sfsizex * sl_info.sfsizey; // allocate memory for data data = (float *) malloc(sfN * sl_info.nrofframes * sizeof(float)); winH = (float *) malloc(sfN * sizeof(float)); winF = (float *) malloc(sfN * sizeof(float)); pc = (float *) malloc(sfN * sizeof(float)); /* Initialise hamming window, fractional hamming & mask */ hanming(winH, sl_info.sfsizex, sl_info.sfsizey, 0.5); frachamming(winF, sl_info.sfsizex, sl_info.sfsizey, sl_info.limApod, 0, NULL); // mask is no longer used... mask = ellmask(sl_info.sfsizex, sl_info.sfsizey, NULL, sl_info.rad_x, sl_info.rad_y); // allocate appropriate memory index = bs_init(&bs_cnt, sl_info); bsc = (float *) malloc(2 * bs_cnt * sizeof(float)); wc = (float *) malloc(bs_cnt * sizeof(float)); // Allocate memory for reconstructed amplitudes & phases amp = (float *) malloc(sfN * sizeof(float)); phs = (float *) malloc(2 * sfN * sizeof(float)); p1 = (float *) malloc(2 * sfN * sizeof(float)); // set flag so as to not allocate new memory later c = NOGO; } // initialise amps, phases & phase consistency to zero memset(bsc, 0.0, 2 * bs_cnt * sizeof(float)); memset(wc, 0.0, bs_cnt * sizeof(float)); memset(amp, 0.0, sfN * sizeof(float)); memset(phs, 0.0, 2 * sfN * sizeof(float)); memset(p1, 0.0, 2 * sfN * sizeof(float)); memset(pc, 0.0, sfN * sizeof(float)); // finally receive the data MPI_Recv(data, sfN * sl_info.nrofframes, MPI_FLOAT, 0, MPI_ANY_TAG, MPI_COMM_WORLD, status); // compute mean of burst //mean(data, sl_info.sfsizex, sl_info.sfsizey, sl_info.nrofframes, temp); /* compute the position of the 'good' average phase parts 3 is an argument here because we deleted: ((int) (alpha[0] * i_rad) > 3 ? (int) (alpha[0] * i_rad) : 3), */ init_shift(sl_info.sfsizex / 2, sl_info.sfsizey / 2, 3, &maxk, &shifts); // create bi-spectrum/weights in non-redundant matrix aphs = bs_ave(data, winF, sl_info, index, bs_cnt, bsc, wc, amp, maxk, shifts); // set snr-threshold bs_snrt(wc, bs_cnt, &sl_info); // phase reconstruction // init phase matrices phs_init(phs, p1, pc, sl_info, maxk, shifts, aphs); // recursive approach rpr(phs, p1, pc, index, bs_cnt, bsc, wc, sl_info); // iterative approach for (i = 0; i < sl_info.max_it; i++) { iwlspr(phs, p1, pc, bsc, wc, index, bs_cnt, sl_info, maxk); if (chkphase(sl_info, phs) < 1.0e-5) break; } // Send back info, so master knows, which subfield burst this was // MPI_TAG will indicate whether we are at the end of the process MPI_Send(&sl_info, 1, MPI_SLAVEINF, 0, NOGO, MPI_COMM_WORLD); // Send back processed data MPI_Send(amp, sfN, MPI_FLOAT, 0, NOGO, MPI_COMM_WORLD); // send back phase MPI_Send(phs, 2 * sfN, MPI_FLOAT, 0, NOGO, MPI_COMM_WORLD); // free some memory free(shifts); shifts = NULL; free(aphs); aphs = NULL; } } // free memory if (data != NULL) free(data); if (winH != NULL) free(winH); if (winF != NULL) free(winF); if (mask != NULL) free(mask); if (pc != NULL) free(pc); if (shifts != NULL) free(shifts); if (amp != NULL) free(amp); if (phs != NULL) free(phs); if (index != NULL) free(index); if (p1 != NULL) free(p1); if (bsc != NULL) free(bsc); if (wc != NULL) free(wc); free(status); MPI_Type_free(&MPI_SLAVEINF); // idle until new data or shutdown Broadcast is sent return GO; } else { // free memory free(status); MPI_Type_free(&MPI_SLAVEINF); // idle until new data or shutdown Broadcast is sent return GO; } }