Commit 8b899c24248604acddbaefeebd1a6a8e0bdd9dcf

Authored by David Mayerich
1 parent 8cfba32f

fixed asynchronous read bugs

stim/biomodels/cellset.h
... ... @@ -15,6 +15,7 @@ protected:
15 15 std::vector<double*> cells; //vector storing field data for each cell
16 16 std::unordered_map<std::string, size_t> fields; //unordered map storing field->index information for each field
17 17 size_t ip[3]; //hard code to position indices (for speed)
  18 +
18 19 void init(){
19 20  
20 21 }
... ... @@ -80,6 +81,13 @@ public:
80 81 return cells[c][idx];
81 82 }
82 83  
  84 + /// returns an ID used to look up a field
  85 + bool exists(std::string f){
  86 + std::unordered_map<std::string, size_t>::iterator iter = fields.find(f);
  87 + if(iter == fields.end()) return false;
  88 + else return true;
  89 + }
  90 +
83 91 /// Return the position of cell [i]
84 92 stim::vec3<double> p(size_t i){
85 93 stim::vec3<double> pos(cells[i][ip[0]], cells[i][ip[1]], cells[i][ip[2]]);
... ...
stim/envi/binary.h
... ... @@ -403,6 +403,48 @@ public:
403 403 return read_pixel(p, i);
404 404 }
405 405  
  406 + /// Reads a block specified by an (x, y, z) position and size using the largest possible contiguous reads
  407 + bool read_block(T* dest, size_t x, size_t y, size_t z, size_t sx, size_t sy, size_t sz){
  408 +
  409 + size_t size_bytes = sx * sy * sz * sizeof(T); //size of the block to read in bytes
  410 +
  411 + size_t start = z * R[0] * R[1] + y * R[0] + x; //calculate the start postion
  412 + size_t start_bytes = start * sizeof(T); //start position in bytes
  413 + file.seekg(start * sizeof(T), std::ios::beg); //seek to the start position
  414 +
  415 +
  416 + if(sx == R[0] && sy == R[1]){ //if sx and sy result in a contiguous volume along z
  417 + file.read((char*)dest, size_bytes); //read the block in one pass
  418 + return true;
  419 + }
  420 +
  421 + if(sx == R[0]){ //if sx is contiguous, read each z-axis slice can be read in one pass
  422 + size_t jump_bytes = (R[1] - sy) * R[0] * sizeof(T); //jump between each slice
  423 + size_t slice_bytes = sx * sy * sizeof(T); //size of the slice to be read
  424 + for(size_t zi = 0; zi < sz; zi++){ //for each z-axis slice
  425 + file.read((char*)dest, slice_bytes); //read the slice
  426 + dest += sx * sy; //move the destination pointer to the next slice
  427 + file.seekg(jump_bytes, std::ios::cur); //skip to the next slice in the file
  428 + }
  429 + return true;
  430 + }
  431 +
  432 + //in this case, x is not contiguous so the volume must be read line-by-line
  433 + size_t jump_x_bytes = (R[0] - sx) * sizeof(T); //number of bytes skipped in the x direction
  434 + size_t jump_y_bytes = (R[1] - sy) * R[0] * sizeof(T) + jump_x_bytes; //number of bytes skipped between slices
  435 + size_t line_bytes = sx * sizeof(T); //size of the line to be read
  436 + size_t zi, yi;
  437 + for(zi = 0; zi < sz; zi++){ //for each slice
  438 + file.read((char*)dest, line_bytes); //read the first line
  439 + for(yi = 1; yi < sy; yi++){ //read each additional line
  440 + dest += sx; //move the pointer in the destination block to the next line
  441 + file.seekg(jump_x_bytes, std::ios::cur); //skip to the next line in the file
  442 + file.read((char*)dest, line_bytes); //read the line to the destination block
  443 + }
  444 + file.seekg(jump_y_bytes, std::ios::cur); //skip to the beginning of the next slice
  445 + }
  446 + }
  447 +
406 448 };
407 449  
408 450 }
... ...
stim/envi/bsq.h
... ... @@ -401,6 +401,79 @@ public:
401 401 size_t batches = (size_t)ceil((double)(Y()) / (double)batch_slices); //calculate the number of batches
402 402 T* ptrDst;
403 403 T* ptrSrc;
  404 + size_t y = 0; //initialize the current y-slice position
  405 + for(size_t c = 0; c < batches; c++){
  406 + if(c == (batches - 1)){
  407 + batch_slices = Y() - (batches - 1) * batch_slices; //if this is the last batch, calculate the remaining # of bands
  408 + jump = (Y() - batch_slices) * X() * sizeof(T);
  409 + batchN = XB * batch_slices;
  410 + batch_bytes = batchN * sizeof(T);
  411 + }
  412 +
  413 + auto in_begin = std::chrono::high_resolution_clock::now();
  414 + hsi<T>::read_block(ptrIn, 0, y, 0, X(), batch_slices, Z()); //read the input block
  415 + y += batch_slices;
  416 + auto in_end = std::chrono::high_resolution_clock::now();
  417 + in_time += std::chrono::duration_cast<std::chrono::milliseconds>(in_end-in_begin).count();
  418 +
  419 + auto calc_begin = std::chrono::high_resolution_clock::now();
  420 +
  421 + for(size_t b = 0; b < Z(); b++){ //for each line, store an XB slice in ptrDest
  422 + ptrSrc = ptrIn + (b * X() * batch_slices);
  423 + ptrDst = ptrOut + (b * X()); //initialize ptrDst to the start of the XB output slice
  424 +
  425 + for(size_t y = 0; y < batch_slices; y++){ //for each band in the current line
  426 + memcpy(ptrDst, ptrSrc, X() * sizeof(T)); //copy the band line from the source to the destination
  427 + ptrSrc += X(); //increment the pointer within the current buffer array (batch)
  428 + ptrDst += X() * Z(); //increment the pointer within the XB slice (to be output)
  429 + }
  430 + }
  431 + auto calc_end = std::chrono::high_resolution_clock::now();
  432 + calc_time += std::chrono::duration_cast<std::chrono::milliseconds>(calc_end-calc_begin).count();
  433 +
  434 + auto out_begin = std::chrono::high_resolution_clock::now();
  435 + target.write((char*)ptrOut, batch_bytes); //write the batch to disk
  436 + auto out_end = std::chrono::high_resolution_clock::now();
  437 + out_time += std::chrono::duration_cast<std::chrono::milliseconds>(out_end-out_begin).count();
  438 + if(PROGRESS) progress = (double)( c + 1 ) / (batches) * 100;
  439 + }
  440 +
  441 + free(ptrIn);
  442 + free(ptrOut);
  443 + target.close();
  444 +
  445 + std::cout<<"BSQ->BIL reads: "<<(double)in_time / (1000 * 60)<<" min"<<std::endl;
  446 + std::cout<<"BSQ->BIL calculations: "<<(double)calc_time / (1000 * 60)<<" min"<<std::endl;
  447 + std::cout<<"BSQ->BIL writes: "<<(double)out_time / (1000 * 60)<<" min"<<std::endl;
  448 +
  449 + return true;
  450 + }
  451 +
  452 + /*bool bil(std::string outname, bool PROGRESS = false){
  453 +
  454 + size_t in_time, out_time, calc_time; //initialize the timing variables
  455 + in_time = out_time = calc_time = 0;
  456 +
  457 + size_t XY = X() * Y(); //number of elements in an input slice
  458 + size_t XB = X() * Z(); //number of elements in an output slice
  459 + size_t XYbytes = XY * sizeof(T); //number of bytes in an input slice
  460 + size_t XBbytes = XB * sizeof(T); //number of bytes in an output slice
  461 + size_t batch_slices = binary<T>::buffer_size / (2*XBbytes); //calculate the number of slices that can fit in memory
  462 + if(Y() < batch_slices) batch_slices = Y(); //if the entire data set will fit in memory, do it
  463 + size_t batchN = XB * batch_slices; //number of elements in a batch
  464 + size_t batch_bytes = batchN * sizeof(T); //calculate the number of bytes in a batch
  465 +
  466 + T* ptrIn = (T*) malloc(batch_bytes); //allocate a large buffer storing the read data
  467 + T* ptrOut = (T*) malloc(batch_bytes); //allocate space for storing an output buffer
  468 +
  469 + size_t jump = (Y() - batch_slices) * X() * sizeof(T); //jump between reads in the input file
  470 +
  471 + std::ofstream target(outname.c_str(), std::ios::binary);
  472 + std::string headername = outname + ".hdr";
  473 +
  474 + size_t batches = (size_t)ceil((double)(Y()) / (double)batch_slices); //calculate the number of batches
  475 + T* ptrDst;
  476 + T* ptrSrc;
404 477 for(size_t c = 0; c < batches; c++){
405 478 file.seekg(c * X() * batch_slices * sizeof(T), std::ios::beg);
406 479  
... ... @@ -450,7 +523,7 @@ public:
450 523 std::cout<<"BSQ->BIL writes: "<<(double)out_time / (1000 * 60)<<" min"<<std::endl;
451 524  
452 525 return true;
453   - }
  526 + }*/
454 527  
455 528 /*/// Convert the current BSQ file to a BIL file with the specified file name.
456 529 bool bil(std::string outname, bool PROGRESS = false){
... ...
stim/envi/hsi.h
... ... @@ -202,6 +202,24 @@ public:
202 202 }
203 203 }
204 204  
  205 + void read_block(T* dest, size_t x, size_t y, size_t z, size_t sx, size_t sy, size_t sz){
  206 + size_t d[3]; //position in the binary coordinate system
  207 + size_t sd[3]; //size in the binary coordinate system
  208 +
  209 + d[O[0]] = x; //set the point in the binary coordinate system
  210 + d[O[1]] = y;
  211 + d[O[2]] = z;
  212 +
  213 + sd[O[0]] = sx; //set the size in the binary coordinate system
  214 + sd[O[1]] = sy;
  215 + sd[O[2]] = sz;
  216 +
  217 + if(!binary<T>::read_block(dest, d[0], d[1], d[2], sd[0], sd[1], sd[2])){
  218 + std::cout<<"error reading block in stim::hsi: ("<<d[0]<<", "<<d[1]<<", "<<d[2]<<") - ["<<sd[0]<<", "<<sd[1]<<", "<<sd[2]<<"]"<<std::endl;
  219 + exit(1);
  220 + }
  221 + }
  222 +
205 223 };
206 224  
207 225 } //end namespace STIM
... ...