/// <summary> /// saves a vector to the database, under a specified Guid /// </summary> /// <param name="vector"> /// the part of the vector which is stored on the local process. /// </param> /// <param name="id"> /// the Guid under which the vector should be stored; must be the same /// on all MPI processes. /// </param> public void SaveVector <T>(IList <T> vector, Guid id) { using (new FuncTrace()) { if (m_fsDriver == null) { throw new NotSupportedException("Can't save data when not connected to database."); } #if DEBUG // never trust the user Guid id0 = id.MPIBroadcast(0); if (id0 != id) { throw new ArgumentException( "Guid differs at least on one MPI process.", nameof(id)); } #endif Exception e = null; try { // save parts using (Stream s = m_fsDriver.GetDistVectorDataStream(true, id, MyRank)) { using (var s2 = new GZipStream(s, CompressionMode.Compress)) { // Use a tuple since the Json format expects one object per // file (with some tricks, we could avoid this, but it's // not really worth the effort) var tuple = new Tuple <DistributedVectorHeader, IList <T> >(null, vector); // save header (only proc 0) // ========================= var _part = (new Partitioning(vector.Count)); if (MyRank == 0) { DistributedVectorHeader header = new DistributedVectorHeader(); header.m_Guid = id; header.UseGzip = !DebugSerialization; long[] part = new long[_part.MpiSize + 1]; for (int i = 0; i < _part.MpiSize; i++) { part[i + 1] = part[i] + _part.GetLocalLength(i); } header.Partitioning = part; tuple = new Tuple <DistributedVectorHeader, IList <T> >(header, vector); } csMPI.Raw.Barrier(csMPI.Raw._COMM.WORLD); serializer.Serialize(s2, tuple, typeof(Tuple <DistributedVectorHeader, IList <T> >)); s2.Close(); s.Close(); } } } catch (Exception ee) { Console.Error.WriteLine(ee.GetType().Name + " on rank " + this.MyRank + " saving vector " + id + ": " + ee.Message); Console.Error.WriteLine(ee.StackTrace); e = ee; } e.ExceptionBcast(); } }
/// <summary> /// Loads a vector from the database /// </summary> /// <param name="id"></param> /// <param name="part"> /// Optional partition of the vector among MPI processors: if null, a /// partition is defined by the loader logic. /// </param> public IList <T> LoadVector <T>(Guid id, ref Partitioning part) { using (new FuncTrace()) { // load header // ----------- DistributedVectorHeader header = null; // load on p0 Exception e = null; try { if (MyRank == 0) { // load header using (var s = m_fsDriver.GetDistVectorDataStream(false, id, 0)) using (var reader = new GZipStream(s, CompressionMode.Decompress)) { header = ((Tuple <DistributedVectorHeader, IList <T> >)serializer.Deserialize(reader, typeof(Tuple <DistributedVectorHeader, IList <T> >))).Item1; reader.Close(); s.Close(); } } } catch (Exception ee) { e = ee; } e.ExceptionBcast(); // broadcast header = header.MPIBroadcast(0); // define partition, if necessary if (part == null) { int L = (int)header.Partitioning.Last(); int i0 = (L * this.MyRank) / this.Size; int ie = (L * (this.MyRank + 1)) / this.Size; part = new Partitioning(ie - i0); } // check size if (part.TotalLength != header.Partitioning.Last()) { throw new ArgumentException("IO error: length of vector to load differs from total length of list."); } // find first part // =============== long myI0; int myLen; myI0 = part.i0; myLen = part.LocalLength; int p = 0; while (header.Partitioning[p] <= myI0) { p++; } p--; // now p is the index of the first vector part // load parts // ========== List <T> ret = new List <T>(part.LocalLength); try { int d = 0; do { IList <T> vecP; using (var s = m_fsDriver.GetDistVectorDataStream(false, id, p)) using (var reader = new GZipStream(s, CompressionMode.Decompress)) { vecP = ((Tuple <DistributedVectorHeader, IList <T> >)serializer.Deserialize(reader, typeof(Tuple <DistributedVectorHeader, IList <T> >))).Item2; reader.Close(); s.Close(); } int srdInd = (int)((myI0 + d) - header.Partitioning[p]); int CopyLen = Math.Min(vecP.Count - srdInd, myLen - d); for (int i = 0; i < CopyLen; i++) { ret.Add(vecP[srdInd + i]); d++; } p++; // next part; } while (d < myLen); } catch (Exception ee) { e = ee; } e.ExceptionBcast(); // return // ====== return(ret); } }