I'm looking for pointers on the best practice for parallel reading and 
preprocessing several files of variable-length time series data. I have 
little familiarity with parallelization, so it feels like I'm missing 
something obvious. I've read the Julia documentation and tried several 
approaches based on it, but with little success.

All pids are on one machine. Each file consists of a fixed-length header + 
NX points of variable precision data (NX varies from file to file). NX is 
stored as a value in each fixed-length header. 

I've come up with two clumsy solutions; the problem(s) are described below. 
Note that, with no parallelization, execution time is ~400% of numpy, 
mostly due to file read speed. 

   1. *pmap file read + preprocess*. Somewhat slow due to overhead of 
   moving data; slightly slower than numpy.
   2. *shared array, parallelize read + downsample*. I can achieve a 20% 
   speedup vs. numpy, but I've only found two ways to make this work.
      - A two-pass approach: open each file twice in a pair of pmap-style 
      @sync loops. 
      - first pass, loop over each file: open, get NX, get timestamp, 
         close, return. 
         - NY = round(Int, sum(NX)*fs_ratio); xx = SharedArray(Float64, 
         (NY,)); set variables for e.g. time indexing.
         - second pass, loop over each file: open, seek to data start, read 
         data, downsample into shared array, close.
         - A single-pass approach with stat():
   - estimate shared array size by summing 
         (stat(file).size-header_size)/(smallest_precision) over each file.
         - initialize shared array of NaNs, loop over each file to read 
         data, delete the leftover NaNs 
      - this runs into memory problems. The lowest precision of some data 
         formats overestimates NX by 8x (e.g. Int4 vs Int32). *
         
It seems like the fastest approach (by far) would be to leave IOStreams 
open (two-pass approach) or to read and preprocess each file into its own 
SharedArray (one-pass approach).

   - With the former approach, I don't know how to pass IOStreams between 
   workers. Is this even possible? I've flailed with approaches like an 
   Array{IOStream,1} filled with values created in my parallel kernel, but I 
   get Bad file descriptor errors when I try to read from any of the 
   resultant IOStreams again. For any stream, isopen(stream) returns true, 
   isreadable(stream) returns true, but the handle is set to @0x00...000. I 
   don't know a workaround, or if one exists.
   - With the latter, if data are stored in a SharedArray created in my 
   parallel kernel, accessing from myid() with e.g. sdata(s) gives #undef 
   for every value of s. What I've read suggests this is by design (same 
   basic problem as https://github.com/JuliaLang/julia/issues/13802 ). What am 
   I doing wrong here?
   

Thanks in advance for any suggestions you can offer.


* Aside, mostly: is there a documented/accepted "fastest" way to read a 
signed twos complement 4 bit integer? 

Reply via email to