[Subject Prev][Subject Next][Thread Prev][Thread Next][Date Index][Thread Index]

[hts-users:04323] A patch to HTS from Google


Hi all,

At Google I've made minor changes to HTS to make it more scalable on large data and added some low-level tuning to make it faster.

Now I'm happy to announce that Google allows me to donate these changes to the HTS community.  Please find the attached patch code.  It is not big; it just adds the following functionalities.
The patch code should be applied to HTS-2.3beta (not HTS-2.2 stable version).  Please run the following command at your HTS root directory.

$ patch -p1 -d . < HTS-2.3beta_Google_patch.txt

This patch code was made manually from the internal version of HTS to make it independent from other internal libraries.  I did some tests after creating this patch, but it may not work on your environment.  Please feel free to post problems/questions about it to the hts-users ML (please don't send these questions to my e-mail address directly).

Cheers,

Heiga
diff -ur HTS-2.3beta/HTKLib/HLabel.c HTS-2.3beta_google/HTKLib/HLabel.c
--- HTS-2.3beta/HTKLib/HLabel.c	2015-11-05 19:13:19.182022088 +0000
+++ HTS-2.3beta_google/HTKLib/HLabel.c	2015-11-06 05:07:06.092968735 +0000
@@ -157,7 +157,7 @@
 /* --------------- Global MLF Data Structures  --------- */
 
 #define MLFCHUNKSIZE 500
-#define MAXMLFS 1000
+#define MAXMLFS 2000
 
 static int      numMLFs = 0;     /* number of MLF files opened */
 static FILE   * mlfile[MAXMLFS]; /* array [0..numMLFs-1] of MLF file */
@@ -1082,6 +1082,14 @@
    strcpy(s,buf);
 }
 
+/* EXPORT->ExtraStrip: Remove extra contexts of form /... from s */
+void ExtraStrip(char *s) {
+   char *p;
+   if ((p = strchr(s,'/')) != NULL) {
+      *p = '\0';
+   }
+}
+
 /* EXPORT->LTriStrip: enable triphone stripping */
 void LTriStrip(Boolean enab)
 {
diff -ur HTS-2.3beta/HTKLib/HLabel.h HTS-2.3beta_google/HTKLib/HLabel.h
--- HTS-2.3beta/HTKLib/HLabel.h	2015-11-05 19:13:19.182022088 +0000
+++ HTS-2.3beta_google/HTKLib/HLabel.h	2015-11-06 05:05:08.631182998 +0000
@@ -341,6 +341,11 @@
    Remove contexts of form A- and +B from s 
 */
 
+void ExtraStrip(char *s);
+/*
+   REmove extra contexts of form /... from char *s.
+*/
+
 void LTriStrip(Boolean enab);
 /*
    When enab is set, all triphone labels with the form A-B+C
diff -ur HTS-2.3beta/HTKLib/HModel.h HTS-2.3beta_google/HTKLib/HModel.h
--- HTS-2.3beta/HTKLib/HModel.h	2015-11-05 19:13:19.186022149 +0000
+++ HTS-2.3beta_google/HTKLib/HModel.h	2015-11-06 05:03:38.057806040 +0000
@@ -93,7 +93,7 @@
 */
 
 #define MACHASHSIZE 250007   /* Size of each HMM Set macro hash table */
-#define PTRHASHSIZE  513   /* Size of each HMM Set ptr map hash table */
+#define PTRHASHSIZE 32769   /* Size of each HMM Set ptr map hash table */
 #define MINMIX  1.0E-5     /* Min usable mixture weight */
 #define LMINMIX -11.5129254649702     /* log(MINMIX) */
 #define MINSWEIGHT 1.0E-5  /* Min usable stream weight */
diff -ur HTS-2.3beta/HTKLib/HParm.c HTS-2.3beta_google/HTKLib/HParm.c
--- HTS-2.3beta/HTKLib/HParm.c	2015-11-05 19:13:19.190022211 +0000
+++ HTS-2.3beta_google/HTKLib/HParm.c	2015-11-06 05:53:06.034792060 +0000
@@ -3459,12 +3459,14 @@
       case sizeof(int32):
          if (!RawReadFloat(&cf->src, (float *) data, n, hparmBin, cf->bSwap)) 
             return(FALSE);
-         cf->crcc=UpdateCRCC(data,n,sizeof(int32),cf->bSwap,cf->crcc);
+         if (cf->saveWithCRC)
+            cf->crcc=UpdateCRCC(data,n,sizeof(int32),cf->bSwap,cf->crcc);
          break;
       case sizeof(short):
          if (!RawReadShort(&cf->src, (short *) data, n, hparmBin, cf->bSwap))
             return(FALSE);
-         cf->crcc=UpdateCRCC(data,n,sizeof(short),cf->bSwap,cf->crcc);
+         if (cf->saveWithCRC)
+            cf->crcc=UpdateCRCC(data,n,sizeof(short),cf->bSwap,cf->crcc);
          break;
       }
       return(TRUE);
diff -ur HTS-2.3beta/HTKLib/HShell.c HTS-2.3beta_google/HTKLib/HShell.c
--- HTS-2.3beta/HTKLib/HShell.c	2015-11-05 19:13:19.194022273 +0000
+++ HTS-2.3beta_google/HTKLib/HShell.c	2015-11-06 13:51:23.005926201 +0000
@@ -1779,6 +1779,13 @@
    }
 }
 
+/* EXPORT->WriteLineBreak: write line break to f */
+void WriteLineBreak(FILE *f, Boolean binary) {
+  if (!binary) {
+    fprintf(f, "\n");
+  }
+}
+
 /* -------------------- File Name Handling ------------------- */
 
 /*
diff -ur HTS-2.3beta/HTKLib/HShell.h HTS-2.3beta_google/HTKLib/HShell.h
--- HTS-2.3beta/HTKLib/HShell.h	2015-11-05 19:13:19.194022273 +0000
+++ HTS-2.3beta_google/HTKLib/HShell.h	2015-11-06 13:51:04.737643686 +0000
@@ -538,6 +538,7 @@
 void WriteInt  (FILE *f, int *i,   int n, Boolean binary);
 void WriteFloat(FILE *f, float *x, int n, Boolean binary);
 void WriteDouble(FILE *f, double *x, int n, Boolean binary);
+void WriteLineBreak(FILE *f, Boolean binary);
 /*
    Write n short/int/float/double(s) to the given file.  
    If binary then binary Write is performed.
diff -ur HTS-2.3beta/HTKLib/HTrain.c HTS-2.3beta_google/HTKLib/HTrain.c
--- HTS-2.3beta/HTKLib/HTrain.c	2015-11-05 19:13:19.194022273 +0000
+++ HTS-2.3beta_google/HTKLib/HTrain.c	2015-11-06 13:48:22.419133054 +0000
@@ -114,6 +114,8 @@
 static int maxIter = 10;               /* max num cluster iterations */
 static int minClustSize = 3;           /* min num vectors in cluster */
 static Boolean ldBinary = TRUE;        /* load/dump in binary */
+static Boolean extraStrip = TRUE;      /* Strip extra contexts while dumping/loading
+                                          accumulated statistics. */
 
 Boolean strmProj = FALSE; 
 
@@ -133,6 +135,7 @@
       if (GetConfInt(cParm,nParm,"MINCLUSTSIZE",&i)) minClustSize = i;
       if (GetConfBool(cParm,nParm,"BINARYACCFORMAT",&b)) ldBinary = b;
       if (GetConfBool(cParm,nParm,"STREAMPROJECTION",&b)) strmProj = b;
+      if (GetConfBool(cParm,nParm,"EXTRASTRIP",&b)) extraStrip = b;
    }
 }
 
@@ -321,6 +324,9 @@
 /* EXPORT->NumSegs: Return num segments in ss */
 int NumSegs(SegStore ss)
 {
+   if (ss == NULL) {  /* empty. */
+      return 0;
+   }
    if (ss->hasfv) 
       return ss->fvSegs->nItems;
    else if (ss->hasvq)
@@ -1426,6 +1432,12 @@
 /* DumpPName: dump physical HMM name */
 static void DumpPName(FILE *f, char *pname)
 {
+   char buf[MAXSTRLEN];
+   if (extraStrip) {
+      strcpy(buf, pname);
+      ExtraStrip(buf);
+      pname = buf;
+   }
    WriteString(f,pname,DBL_QUOTE);
    fprintf(f,"\n");
 }
@@ -1448,22 +1460,35 @@
 /* DumpWtAcc: dump wt acc to file f */
 static void DumpWtAcc(FILE *f, WtAcc *wa)
 {
-   WriteVector(f,wa->c,ldBinary);
    WriteFloat(f,&(wa->occ),1,ldBinary);
-   if (!ldBinary) fprintf(f,"\n");
+   if (wa->occ == 0.0) {
+     WriteLineBreak(f, ldBinary);
+     return;
+   }
+   WriteVector(f,wa->c,ldBinary);
+   WriteLineBreak(f, ldBinary);
 }
 
 /* DumpMuAcc: dump mean acc to file f */
 static void DumpMuAcc(FILE *f, MuAcc *ma)
 {
-   WriteVector(f,ma->mu,ldBinary);
    WriteFloat(f,&(ma->occ),1,ldBinary);
-   if (!ldBinary) fprintf(f,"\n");
+   if (ma->occ == 0.0) {
+     WriteLineBreak(f, ldBinary);
+     return;
+   }
+   WriteVector(f,ma->mu,ldBinary);
+   WriteLineBreak(f, ldBinary);
 }
 
 /* DumpVaAcc: dump variance acc to file f */
 static void DumpVaAcc(FILE *f, VaAcc *va, CovKind ck)
 {
+   WriteFloat(f,&(va->occ),1,ldBinary);
+   if (va->occ == 0.0) {
+     WriteLineBreak(f, ldBinary);
+     return;
+   }
    switch(ck){
    case DIAGC:
    case INVDIAGC:
@@ -1476,8 +1501,7 @@
    default:
       HError(7170,"DumpVaAcc: bad cov kind");
    }
-   WriteFloat(f,&(va->occ),1,ldBinary);
-   if (!ldBinary) fprintf(f,"\n");
+   WriteLineBreak(f, ldBinary);
 }
 
 /* DumpTrAcc: dump transition acc to file f */
@@ -1497,8 +1521,8 @@
    if (!ldBinary) fprintf(f,"\n");
 }
 
-/* GetDumpFile: Process dump file name and open it */
-static FILE * GetDumpFile(char *name, int n)
+/* EXPORT -> GetDumpFile: Process dump file name and open it */
+FILE * GetDumpFile(char *name, int n)
 {
    char buf[MAXSTRLEN],num[20];
    int i,j,k,len,nlen;
@@ -1541,6 +1565,7 @@
       DumpPName(f,hss.mac->id->name);     
       i = (int)((long) hmm->hook);
       WriteInt(f,&i,1,ldBinary);
+      WriteLineBreak(f,ldBinary);
       while (GoNextState(&hss,TRUE)) {
          DumpStateOcc(f,hset,hss.si);
          while (GoNextStream(&hss,TRUE)) {
@@ -1601,6 +1626,10 @@
    float f;
    Vector cTemp;
    
+   ReadFloat(src,&f,1,ldBinary);
+   if (f == 0.0) {
+     return;
+   }
    cTemp = CreateVector(&gstack,numMixtures);
    ReadVector(src,cTemp,ldBinary);
    for (m=1;m<=numMixtures;m++){
@@ -1608,7 +1637,6 @@
        HError(7191, "Infinite WtAcc!");
      wa->c[m] += cTemp[m];
    }
-   ReadFloat(src,&f,1,ldBinary);
    wa->occ += f;
    FreeVector(&gstack,cTemp);
 }
@@ -1620,6 +1648,10 @@
    Vector vTemp;
    float f;
    
+   ReadFloat(src,&f,1,ldBinary);
+   if (f == 0.0) {
+     return;
+   }
    vTemp = CreateVector(&gstack,vSize);
    ReadVector(src,vTemp,ldBinary);
    for (k=1;k<=vSize;k++){
@@ -1627,7 +1659,6 @@
        HError(7191, "Infinite MuAcc!");
       ma->mu[k] += vTemp[k];
    }
-   ReadFloat(src,&f,1,ldBinary);
    ma->occ += f;
    FreeVector(&gstack,vTemp);
 }
@@ -1640,6 +1671,10 @@
    TriMat mTemp;
    float f;
    
+   ReadFloat(src,&f,1,ldBinary);
+   if (f == 0.0) {
+     return;
+   }
    switch(ck){
    case DIAGC:
    case INVDIAGC:
@@ -1663,7 +1698,6 @@
       FreeTriMat(&gstack,mTemp);
       break;
    }
-   ReadFloat(src,&f,1,ldBinary);
    va->occ += f;
 }
 
@@ -1690,12 +1724,19 @@
 static void CheckPName(Source *src, char *pname)
 {
    int c;
-   char buf[MAXSTRLEN];
+   char buf[MAXSTRLEN], name[MAXSTRLEN];
 
    ReadString(src,buf);
    c = GetCh(src);
    if (c != '\n')
       HError(7150,"CheckPName: Cant find EOL");
+
+   if (extraStrip) {
+     strcpy(name,pname);
+     ExtraStrip(name);
+     pname = name;
+   }
+
    if (strcmp(pname,buf) != 0)
       HError(7150,"CheckPName: expected %s got %s",pname,buf);
 }
diff -ur HTS-2.3beta/HTKLib/HTrain.h HTS-2.3beta_google/HTKLib/HTrain.h
--- HTS-2.3beta/HTKLib/HTrain.h	2015-11-05 19:13:19.194022273 +0000
+++ HTS-2.3beta_google/HTKLib/HTrain.h	2015-11-06 05:42:39.429309505 +0000
@@ -179,7 +179,7 @@
    Create and return an empty segment store suitable for observations
    of form obs.  Each segment is an ordered sequence of observations with
    blkSize == segLen.  A segment store is a sequence of segments with
-   blkSize = 100.
+   blkSize = 10000.
 */
 
 void LoadSegment(SegStore ss, HTime start, HTime end, ParmBuf pbuf);
@@ -335,6 +335,8 @@
    given HMM.
 */
 
+FILE * GetDumpFile(char *name, int n);
+
 FILE * DumpAccsParallel(HMMSet *hset, char *fname, int n, UPDSet uFlags, int index);
 FILE * DumpAccs(HMMSet *hset, char *fname, UPDSet uFlags, int n);
 /* 
diff -ur HTS-2.3beta/HTKTools/HCompV.c HTS-2.3beta_google/HTKTools/HCompV.c
--- HTS-2.3beta/HTKTools/HCompV.c	2015-11-05 19:13:19.198022335 +0000
+++ HTS-2.3beta_google/HTKTools/HCompV.c	2015-11-06 13:52:24.370875188 +0000
@@ -105,6 +105,7 @@
 #include "HParm.h"
 #include "HLabel.h"
 #include "HModel.h"
+#include "HTrain.h"
 #include "HUtil.h"
 
 /* -------------------------- Trace Flags & Vars ------------------------ */
@@ -137,6 +138,7 @@
 static float vFloorScale = 0.0;     /* if >0.0 then vFloor scaling */
 static Vector vFloorScaleStr = NULL; /* vFloorScale for each stream */
 static int nShowElem = 12;           /* # of elements to be shown */
+static int parallel_mode = -1;       /* enable parallel execution mode */
 
 /* Major Data Structures */
 static MLink macroLink;             /* Link to specific HMM macro */
@@ -151,7 +153,7 @@
    DMatrix      inv;                /* acc for sum of squares (full) */
    DVector      var;                /* acc for sum of squares (diag) */
    Covariance   fixed;              /* fixed (co)variance values */
-   long         totalCount;         /* total number of vector samples */
+   double       totalCount;         /* total number of vector samples */
 } CovAcc;
 static CovAcc accs[SMAX];           /* one CovAcc for each stream */
 static Boolean fullcNeeded[SMAX];   /* true for each stream that needs full
@@ -219,6 +221,7 @@
    printf(" -o fn   Store new hmm def in fn (name only)  outDir/srcfn\n");
    printf(" -p s    path pattern for CMV                 none\n");
    printf(" -q nmv  output type flags for CMV            m\n");
+   printf(" -r n    set parallel mode to N               off\n");
    printf(" -v f    Set minimum variance to f            0.0\n");
    PrintStdOpts("BCFGHILMX");
    printf("\n\n");
@@ -293,7 +296,7 @@
          accs[s].fixed.var=CreateVector(&gstack,V);
          ZeroDVector(accs[s].var);
       }
-      accs[s].totalCount = 0;
+      accs[s].totalCount = 0.0;
    }
 
    /* Create an object to hold the input parameters */
@@ -320,6 +323,79 @@
    }
 }
 
+
+/* Dump CovAcc to a file. */
+void DumpCovAccs() {
+  char accs_filename[MAXFNAMELEN];
+  MakeFN("HCompV$.acc", outDir, NULL, accs_filename);
+  FILE *f = GetDumpFile(accs_filename, parallel_mode);
+
+  /* Dump accumulators for the mean and variance to f */
+  int s;
+  for (s = 1; s <= hset.swidth[0]; ++s) {
+    WriteShort(f, &hset.swidth[s], 1, saveBinary);
+    WriteDVector(f, accs[s].meanSum, saveBinary);
+    if (fullcNeeded[s]) {
+      WriteDMatrix(f, accs[s].inv, saveBinary);
+    } else {
+      WriteDVector(f, accs[s].var, saveBinary);
+    }
+    WriteDouble(f, &accs[s].totalCount, 1, saveBinary);
+  }
+  fclose(f);
+}
+
+/* Load dumped CovAcc and add it to CovAcc. */
+void LoadCovAccs(char *accs_filename) {
+  Source src;
+  if (InitSource(accs_filename, &src, NoFilter) < SUCCESS) {
+    HError(7110, "LoadCovAccs: Can't open file %s", accs_filename);
+  }
+  int i, j, s, k;
+  for (s = 1; s <= hset.swidth[0]; ++s) {
+    short vec_size;
+    ReadShort(&src, &vec_size, 1, saveBinary);
+    if (vec_size != hset.swidth[s]) {
+      HError(9999, "LoadCovAccs: mismatch in stream width[%d] (%d vs %d)",
+             s, hset.swidth[s], vec_size);
+    }
+    DVector vec = CreateDVector(&gstack, vec_size);
+    DMatrix mat = CreateDMatrix(&gstack, vec_size, vec_size);;
+    ReadDVector(&src, vec, saveBinary);
+    for (k = 1; k <= vec_size; ++k) {
+      if (!finite(vec[k])) {
+        HError(7191, "LoadCovAccs: Infinite CovAcc!");
+      }
+      accs[s].meanSum[k] += vec[k];
+    }
+    if (!fullcNeeded[s]) {
+      ReadDVector(&src, vec, saveBinary);
+      for (k = 1; k <= vec_size; ++k) {
+        if (!finite(vec[k])) {
+          HError(7191, "LoadCovAccs: Infinite CovAcc!");
+        }
+        accs[s].var[k] += vec[k];
+      }
+    } else {
+      ReadDMatrix(&src, mat, saveBinary);
+      for (i = 1; i <= vec_size; ++i) {
+        for (j = 1; j <= vec_size; ++j) {
+          if (!finite(mat[i][j])) {
+            HError(7191, "LoadCovAccs: Infinite CovAcc!");
+          }
+          accs[s].inv[i][j] += mat[i][j];
+        }
+      }
+    }
+    double total_count;
+    ReadDouble(&src, &total_count, 1, saveBinary);
+    if (!finite(total_count)) {
+      HError(7191, "LoadCovAccs: Infinite CovAcc!");
+    }
+    accs[s].totalCount += total_count;
+  }
+}
+
 /* ----------------------[Co]Variance Estimation ---------------------- */
 
 /* CalcCovs: calculate covariance of speech data */
@@ -331,10 +407,10 @@
    TriMat triMat;
    
    for (s=1; s<=hset.swidth[0]; s++){  /* For each stream   */
-      if (accs[s].totalCount<2)
-         HError(2021,"CalcCovs: Only %ld speech frames accumulated for stream %d", accs[s].totalCount, s);
+      if (accs[s].totalCount<2.0)
+         HError(2021,"CalcCovs: Only %.0lf speech frames accumulated for stream %d", accs[s].totalCount, s);
       if (trace&T_TOP)
-         printf("%ld speech frames accumulated for stream %d\n", accs[s].totalCount, s);
+         printf("%.0lf speech frames accumulated for stream %d\n", accs[s].totalCount, s);
       n = (double)accs[s].totalCount; /* to prevent rounding to integer below */
       V = hset.swidth[s];
       for (x=1; x<=V; x++)            /* For each coefficient ... */
@@ -498,7 +574,7 @@
          } else                         /* accumulate var */
                accs[s].var[x] += val*val;
          }
-         accs[s].totalCount++;   /* accumulate occ */
+         accs[s].totalCount += 1.0;   /* accumulate occ */
       }
    }
 }
@@ -865,7 +941,7 @@
          HError(2019,"HCompV: Bad switch %s; must be single letter",s);
       switch(s[0]){
       case 'f':
-         if (NextArg() != FLOATARG)
+         if (NextArg() != FLOATARG && NextArg() != INTARG)
             HError(2019,"HCompV: Variance floor scale expected");
          vFloorScale = GetChkedFlt(0.0,100.0,s);
          break;
@@ -880,8 +956,11 @@
       case 'o':
          outfn = GetStrArg();
          break;     
+      case 'r':
+        parallel_mode = GetChkedInt(-1, 2000, s);
+        break;
       case 'v':
-         if (NextArg() != FLOATARG)
+         if (NextArg() != FLOATARG && NextArg() != INTARG)
             HError(2019,"HCompV: Minimum variance level expected");
          minVar = GetChkedFlt(0.0,100.0,s);
          break;
@@ -970,17 +1049,32 @@
          if (NextArg()!=STRINGARG)
             HError(2019,"HCompV: Training data file name expected");
          datafn = GetStrArg();
-         LoadFile(datafn);
+         if (parallel_mode == 0) {
+            LoadCovAccs(datafn);
+         } else {
+            LoadFile(datafn);
+         }
       } while (NumArgs()>0);
-      SetCovs();
-      FixGConsts(hmmLink);
-      SaveModel(outfn);   
-      if (trace&T_TOP)
-         printf("Output written to directory %s\n",(outDir==NULL)?"./":outDir);
-         PutVFloor();
+      if (parallel_mode <= 0) {
+         SetCovs();
+         FixGConsts(hmmLink);
+         SaveModel(outfn);   
+         if (trace&T_TOP)
+            printf("Output written to directory %s\n",(outDir==NULL)?"./":outDir);
+        PutVFloor();
+      } else {
+         DumpCovAccs();
+         if (trace & T_TOP) {
+            printf("Accumulated statistics written to directory %s\n",
+                   (outDir == NULL) ? "./" : outDir);
+         }
+      }
       FreeVector(&gstack,vFloorScaleStr);
    }
    else {
+      if (parallel_mode >= 0) {
+         HError(9999, "HCompV: parallel mode is not supported for computing CMV.");
+      }
       /* report export data type */
       ReportOutput();
       /* init input buffer mem heap */
diff -ur HTS-2.3beta/HTKTools/HInit.c HTS-2.3beta_google/HTKTools/HInit.c
--- HTS-2.3beta/HTKTools/HInit.c	2015-11-05 19:13:19.206022458 +0000
+++ HTS-2.3beta_google/HTKTools/HInit.c	2015-11-06 14:08:15.441591382 +0000
@@ -124,7 +124,9 @@
 static int minSeg    = 3;           /* min segments to train a model */
 static Boolean  newModel = TRUE;    /* enable initial uniform segmentation */
 static Boolean saveBinary = FALSE;  /* save output in binary  */
+static Boolean ldBinary = TRUE;     /* load/dump in binary */
 static Boolean firstTime = TRUE;    /* Flag used to enable InitSegStore */
+static int parallel_mode = -1;      /* enable parallel execution mode */
 static FileFormat dff=UNDEFF;       /* data file format */
 static FileFormat lff=UNDEFF;       /* label file format */
 static char *hmmfn;                 /* HMM definition file name (& part dir)*/
@@ -135,6 +137,8 @@
 static ConfParam *cParm[MAXGLOBS];   /* configuration parameters */
 static int nParm = 0;               /* total num params */
 static Vector vFloor[SMAX];         /* variance floor - default is all zero */
+static Boolean use_uniform_align = FALSE;  /* Use UniformAlign rather than ViterbiAlign */
+                                        /* at the first iteration */
 
 /* Major Data Structures plus related global vars*/
 static HMMSet hset;              /* The current unitary hmm set */
@@ -166,10 +170,12 @@
 /* SetConfParms: set conf parms relevant to HInit  */
 void SetConfParms(void)
 {
+   Boolean b;
    int i;
 
    nParm = GetConfig("HINIT", TRUE, cParm, MAXGLOBS);
    if (nParm>0) {
+      if (GetConfBool(cParm, nParm, "BINARYACCFORMAT", &b)) ldBinary = b;
       if (GetConfInt(cParm,nParm,"TRACE",&i)) trace = i;
    }
 }
@@ -186,6 +192,8 @@
    printf(" -m N    Set min segments needed              3\n");
    printf(" -n      Update hmm (suppress uniform seg)    off\n");
    printf(" -o fn   Store new hmm def in fn (name only)  outDir/srcfn\n");
+   printf(" -p N    set parallel mode to N               off\n");
+   printf(" -q      Use uniform alignment for init       off\n");
    printf(" -u mvwt Update m)eans v)ars w)ghts t)rans    mvwt\n");
    printf(" -v f    Set minimum variance to f            1.0E-2\n");
    printf(" -w f    set mix wt/disc prob floor to f      0.0\n");
@@ -216,11 +224,13 @@
 int main(int argc, char *argv[])
 {
    char *datafn, *s;
-   int nSeg;
+   int nSeg = 0;
+   LogFloat newP = 0.0;
    void Initialise(void);
    void LoadFile(char *fn);
    void EstimateModel(void);
    void SaveModel(char *outfn);
+   void UpdateParameters(void);
    
    if(InitShell(argc,argv,hinit_version,hinit_vc_id)<SUCCESS)
       HError(2100,"HInit: InitShell failed");
@@ -255,12 +265,18 @@
          segLab = GetStrArg();
          break;
       case 'm':
-         minSeg = GetChkedInt(1,1000,s); break;
+         minSeg = GetChkedInt(0,1000,s); break;
       case 'n':
          newModel = FALSE; break;
       case 'o':
          outfn = GetStrArg();
          break;
+      case 'p':
+         parallel_mode = GetChkedInt(-1, 2000, s);
+         break;
+      case 'q':
+         use_uniform_align = TRUE;
+         break;
       case 'u':
          SetuFlags(); break;
       case 'v':
@@ -320,32 +336,61 @@
    hmmfn = GetStrArg();
    Initialise();
    do {
-      if (NextArg()!=STRINGARG)
-         HError(2119,"HInit: training data file name expected");
+      if (NextArg() != STRINGARG)
+         HError(2119, "HInit: training data file name expected");
       datafn = GetStrArg();
-      LoadFile(datafn);
-   } while (NumArgs()>0);
-   nSeg = NumSegs(segStore);
+      if (parallel_mode == 0) {
+         /* Load dumped accumulated stats. */
+         Source src = LoadAccs(&hset, datafn, uFlags);
+         float tmpFlt;
+         ReadFloat(&src, &tmpFlt, 1, ldBinary);
+         newP += tmpFlt;
+         int tmpInt;
+         ReadInt(&src, &tmpInt, 1, ldBinary);
+         nSeg += tmpInt;
+         CloseSource(&src);
+      } else {
+         LoadFile(datafn);
+      }
+   } while (NumArgs() > 0);
+   if (parallel_mode != 0) {
+      nSeg = NumSegs(segStore);
+   }
    if (nSeg < minSeg)
       HError(2121,"HInit: Too Few Observation Sequences [%d]",nSeg);
    if (trace&T_TOP) {
       printf("%d Observation Sequences Loaded\n",nSeg);
       fflush(stdout);
    }
-   EstimateModel();
-   SaveModel(outfn);
+   if (nSeg > 0) {
+      if (parallel_mode == 0) {
+         newP /= (float)(nSeg);
+         if (newP != 0.0) {
+            /* newP == 0 indicates that it is by UniformAlign initialization. */
+            printf("Average LogP =%12.5f\n", newP);
+            fflush(stdout);
+         }
+         UpdateParameters();
+      } else {
+         EstimateModel();
+      }
+   } else {
+      if (parallel_mode > 0) {
+         EstimateModel();
+      } else {
+         if (trace & T_TOP) {
+            printf("Bypassed parameter estimation.\n");
+            fflush(stdout);
+         }
+      }
+   }
+   if (parallel_mode <= 0) {
+      SaveModel(outfn);
+   }
    if (trace&T_TOP)
       printf("Output written to directory %s\n",
              outDir==NULL?"current":outDir);
-   
-   InitMem();   InitLabel();
-   InitMath();  InitSigP();
-   InitWave();  InitAudio();
-   InitVQ();    InitModel();
-   if(InitParm()<SUCCESS)  
-      HError(2100,"HInit: InitParm failed");
-   InitTrain(); InitUtil();
-   
+
    ResetUtil();
    ResetTrain();
    ResetParm();
@@ -418,6 +463,7 @@
    if ((hset.hsKind==DISCRETEHS)||(hset.hsKind==TIEDHS))
       uFlags = (UPDSet) (uFlags & (~(UPMEANS|UPVARS)));
    AttachAccs(&hset, &gstack, uFlags);
+   ZeroAccs(&hset, uFlags);
 
    /* Get a pointer to the physical HMM and set related globals */
    hmmId = GetLabId(base,FALSE);   
@@ -449,7 +495,7 @@
    SetStreamWidths(info->tgtPK,info->tgtVecSize,hset.swidth,&eSep);
    obs = MakeObservation(&gstack,hset.swidth,info->tgtPK,
                          ((hset.hsKind==DISCRETEHS) ? TRUE:FALSE),eSep);
-   segStore = CreateSegStore(&segmentStack,obs,10);
+   segStore = CreateSegStore(&segmentStack,obs,10000);
    firstTime = FALSE;
 }
 
@@ -485,7 +531,7 @@
    LLink p;
    Observation obs;
 
-   if((pbuf=OpenBuffer(&bufferStack, fn, 10, dff, FALSE_dup, FALSE_dup))==NULL)
+   if((pbuf=OpenBuffer(&bufferStack, fn, 0, dff, FALSE_dup, FALSE_dup))==NULL)
       HError(2150,"LoadFile: Config parameters invalid");
    GetBufferInfo(pbuf,&info);
    CheckData(fn,info);
@@ -561,7 +607,7 @@
          seqMat[i][j] = (Sequence*)New(&gstack, nKindS*sizeof(Sequence));
          --seqMat[i][j];
          for(k=1; k<=nKindS; k++)
-            seqMat[i][j][k] = CreateSequence(&sequenceStack, 1000);
+            seqMat[i][j][k] = CreateSequence(&sequenceStack, 10000);
       }
    }
    return seqMat;
@@ -903,6 +949,32 @@
    }
 }
 
+/* UniformAlign: align the segment_index'th segment uniformly.  It does the same
+   job as UCollectData if number of mixture component per stream is 1. */
+LogFloat UniformAlign(int segment_index, int segment_length,
+                      IntVec states, IntVec *mixes) {
+  float num_observations_per_state =
+      (float)(segment_length) / (float)(nStates - 2);
+  if (num_observations_per_state < 1.0) {
+    HError(2122, "UniformAlign: segment too short[%d]", segment_length);
+  }
+  int frame;
+  for (frame = 1; frame <= segment_length; ++frame) {
+    Observation obs = GetSegObs(segStore, segment_index, frame);
+    int state_index = (int)((float)(frame - 1) /
+                       num_observations_per_state + 2);
+    if (state_index <= 1 || state_index >= nStates) {
+      HError(2122, "UniformAlign: state index (%d) out of range",
+             state_index);
+    }
+    states[frame] = state_index;
+  }
+  if (mixes != NULL)  {  /* not DISCRETE */
+    FindBestMixes(segment_index, segment_length, states, mixes);
+  }
+  return 0.0;  /* UniformAlign does not compute prob.  Return 0 as a dummy. */
+}
+
 /* ViterbiAlign: align the segNum'th segment.  For each frame k, store aligned
    state in states and mostly likely mix comp in mixes.  Return logP. */
 LogFloat ViterbiAlign(int segNum,int segLen, IntVec states, IntVec *mixes)
@@ -1382,38 +1454,59 @@
    int i,iter,numSegs,segLen;    
    IntVec states;  /* array[1..numSegs] of State */
    IntVec *mixes;  /* array[1..S][1..numSegs] of MixComp */
-
-   if (trace&T_TOP) printf("Starting Estimation Process\n");
-   if (newModel){
-      UniformSegment();
-   }
-   totalP=LZERO;
-   for (iter=1; !converged && iter<=maxIter; iter++){
-      ZeroAccs(&hset, uFlags);              /* Clear all accumulators */
+   totalP = LZERO;
+   const int initial_iteration = (newModel) ? 0 : 1;
+   const int max_iteration = (parallel_mode >= 0) ? initial_iteration : maxIter;
+   for (iter = initial_iteration; !converged && iter <= max_iteration; iter++) {
+      if (iter == 0) {
+         if (!use_uniform_align) {
+            if (trace & T_UNI) printf("Initializing HMM by UniformSegment().\n");
+               UniformSegment();
+            continue;
+         } else {
+            /* UniformAlign() will be called later. */
+            if (trace & T_UNI) printf("Initializing HMM by UniformAlign().\n");
+         }
+      }
+      ZeroAccs(&hset, uFlags); /* Clear all accumulators */
       numSegs = NumSegs(segStore);
       /* Align on each training segment and accumulate stats */
-      for (newP=0.0,i=1;i<=numSegs;i++) {
-         segLen = SegLength(segStore,i);
-         states = CreateIntVec(&gstack,segLen);
-         mixes  = (hset.hsKind==DISCRETEHS)? NULL : CreateMixes(&gstack,segLen);
-         newP += ViterbiAlign(i,segLen,states,mixes);
-         if (trace&T_ALN) ShowAlignment(i,segLen,states,mixes);
-         UpdateCounts(i,segLen,states,mixes);
-         FreeIntVec(&gstack,states); /* disposes mixes too */
+      for (newP = 0.0, i = 1; i <= numSegs; i++) {
+         segLen = SegLength(segStore, i);
+         states = CreateIntVec(&gstack, segLen);
+         mixes = (hset.hsKind == DISCRETEHS) ? NULL : CreateMixes(&gstack, segLen);
+         if (iter == 0 && use_uniform_align) {
+            newP += UniformAlign(i, segLen, states, mixes);
+         } else {
+            newP += ViterbiAlign(i, segLen, states, mixes);
+         }
+         if (trace & T_ALN) ShowAlignment(i, segLen, states, mixes);
+            UpdateCounts(i, segLen, states, mixes);
+            FreeIntVec(&gstack, states); /* disposes mixes too */
+      }
+      if (parallel_mode > 0) {
+         /* dump HMM accs */
+         char acc_base[MAXSTRLEN], accs_file[MAXFNAMELEN];
+         snprintf(acc_base, MAXSTRLEN, "%s$.acc", segLab);
+         MakeFN(acc_base, outDir, NULL, accs_file);
+         FILE *f = DumpAccs(&hset, accs_file, uFlags, parallel_mode);
+         WriteFloat(f, &newP, 1, ldBinary);
+         WriteInt(f, &numSegs, 1, ldBinary);
+         fclose(f);
+         return;
       }
       /* Update parameters or quit */
-      newP /= (float)numSegs;
+      newP /= (float)(numSegs);
       delta = newP - totalP;
-      converged = ((iter>1) && (fabs(delta) < epsilon)) ? TRUE:FALSE;
-      if (!converged)
-         UpdateParameters();
+      converged = ((iter > 1) && (fabs(delta) < epsilon)) ? TRUE : FALSE;
+      if (!converged) UpdateParameters();
       totalP = newP;
-      if (trace & T_TOP){
-         printf("Iteration %d: Average LogP =%12.5f",iter,totalP);
+      if (trace & T_TOP && iter > 0) {
+         printf("Iteration %d: Average LogP =%12.5f", iter, totalP);
          if (iter > 1)
-            printf("  Change =%12.5f\n",delta);
+            printf("  Change =%12.5f\n", delta);
          else
-            printf("\n");
+           printf("\n");
          fflush(stdout);
       }
    }
diff -ur HTS-2.3beta/HTKTools/HLEd.c HTS-2.3beta_google/HTKTools/HLEd.c
--- HTS-2.3beta/HTKTools/HLEd.c	2015-11-05 19:13:19.206022458 +0000
+++ HTS-2.3beta_google/HTKTools/HLEd.c	2015-11-06 10:51:59.475493145 +0000
@@ -236,7 +236,7 @@
          dictFn = GetStrArg();
          break;
       case 'g':
-         if (NextArg() != FLOATARG)
+         if (NextArg() != FLOATARG && NextArg() != INTARG)
             HError(1219,"HLEd: Min fill gap expected (100ns units)");
          minGap = GetChkedFlt(0.0,100000000.0,s); 
          break;
diff -ur HTS-2.3beta/HTKTools/HLRescore.c HTS-2.3beta_google/HTKTools/HLRescore.c
--- HTS-2.3beta/HTKTools/HLRescore.c	2015-11-05 19:13:19.206022458 +0000
+++ HTS-2.3beta_google/HTKTools/HLRescore.c	2015-11-06 10:52:58.196396211 +0000
@@ -337,22 +337,22 @@
          labOutExt = GetStrArg(); break;
       
       case 'p':
-         if (NextArg() != FLOATARG)
+         if (NextArg() != FLOATARG && NextArg() != INTARG)
             HError (4019, "HLRescore: word insertion penalty expected");
          wordPen = GetChkedFlt (-1000.0, 1000.0, s); 
          break;
       case 's':
-         if (NextArg() != FLOATARG)
+         if (NextArg() != FLOATARG && NextArg() != INTARG)
             HError (4019, "HLRescore:  grammar scale factor expected");
          lmScale = GetChkedFlt (0.0, 1000.0, s); 
          break;
       case 'a':
-         if (NextArg() != FLOATARG)
+         if (NextArg() != FLOATARG && NextArg() != INTARG)
             HError (4019, "HLRescore:  acoustic scale factor expected");
          acScale = GetChkedFlt (0.0, 1000.0, s); 
          break;
       case 'r':
-         if (NextArg() != FLOATARG)
+         if (NextArg() != FLOATARG && NextArg() != INTARG)
             HError (4019, "HLRescore:  pronunciation scale factor expected");
          prScale = GetChkedFlt (0.0, 1000.0, s); 
          break;
@@ -362,19 +362,19 @@
          break;
 
       case 't':
-         if (NextArg() != FLOATARG)
+         if (NextArg() != FLOATARG && NextArg() != INTARG)
             HError (4019, "HLRescore:  lattice pruning threshold expected");
          pruneInThresh = GetChkedFlt (0.0, 10000.0, s); 
          pruneInLat = TRUE;
-         if (NextArg() == FLOATARG)
+         if (NextArg() == FLOATARG && NextArg() != INTARG)
             pruneInArcsPerSec = GetChkedFlt (0.0, 150000.0, s);
          break;
       case 'u':
-         if (NextArg() != FLOATARG)
+         if (NextArg() != FLOATARG && NextArg() != INTARG)
             HError (4019, "HLRescore:  lattice pruning threshold expected");
          pruneOutThresh = GetChkedFlt (0.0, 10000.0, s); 
          pruneOutLat = TRUE;
-         if (NextArg() == FLOATARG)
+         if (NextArg() == FLOATARG && NextArg() != INTARG)
             pruneOutArcsPerSec = GetChkedFlt (0.0, 150000.0, s);
          break;
 
diff -ur HTS-2.3beta/HTKTools/HMGenS.c HTS-2.3beta_google/HTKTools/HMGenS.c
--- HTS-2.3beta/HTKTools/HMGenS.c	2015-11-05 19:13:19.206022458 +0000
+++ HTS-2.3beta_google/HTKTools/HMGenS.c	2015-11-06 10:53:19.812729009 +0000
@@ -384,7 +384,7 @@
          outPdf = TRUE;
          break;
       case 'r':
-         if (NextArg() != FLOATARG)
+         if (NextArg() != FLOATARG && NextArg() != INTARG)
             HError(2119, "HMGenS: Speaking rate value (float) expected");
          speakRate = GetChkedFlt(0.0, 3.0, s);
          break;
diff -ur HTS-2.3beta/HTKTools/HRest.c HTS-2.3beta_google/HTKTools/HRest.c
--- HTS-2.3beta/HTKTools/HRest.c	2015-11-05 19:13:19.210022520 +0000
+++ HTS-2.3beta_google/HTKTools/HRest.c	2015-11-06 14:09:38.514875597 +0000
@@ -132,7 +132,9 @@
 static float epsilon = 1.0E-4;   /* convergence criterion */
 static int minSeg    = 3;        /* min segments to train a model */
 static Boolean firstTime = TRUE; /* Flag used to enable InitSegStore */
+static int parallel_mode = -1;   /* enable parallel execution mode */
 static Boolean saveBinary = FALSE;  /* save output in binary  */
+static Boolean ldBinary = TRUE;     /* load/dump in binary */
 static Boolean calcDuration = FALSE; /* save duration */
 static FileFormat dff=UNDEFF;    /* data file format */
 static FileFormat lff=UNDEFF;    /* label file format */
@@ -156,7 +158,7 @@
 static HSetKind hsKind;          /* kind of the HMM system */
 static int maxMixes;       /* max num mixtures across all streams */
 static int maxMixInS[SMAX];/* array[1..swidth[0]] of max mixes */
-static int nSeg;           /* num training segments */
+static int nSeg = 0;       /* num training segments */
 static int nTokUsed;       /* actual number of tokens used */
 static int maxT,minT,T;    /* max,min and current segment lengths */
 static DMatrix alpha;      /* array[1..nStates][1..maxT] of forward prob */
@@ -196,6 +198,7 @@
    if (nParm>0) {
       if (GetConfInt(cParm,nParm,"TRACE",&i)) trace = i;
       if (GetConfBool(cParm,nParm,"SAVEBINARY",&b)) saveBinary = b;
+      if (GetConfBool(cParm, nParm,"BINARYACCFORMAT",&b)) ldBinary = b;
       if (GetConfFlt(cParm,nParm,"VDEFUNCT",&d)) vDefunct = d;
    }
 }
@@ -211,6 +214,7 @@
    printf(" -l s    Set segment label to s               none\n");
    printf(" -m N    Set min segments needed              3\n");
    printf(" -o fn   Store new hmm def in fn (name only)               outDir/srcfn\n");
+   printf(" -p N    set parallel mode to N               off\n");
    printf(" -t      Disable short segment rejection      on\n");
    printf(" -u tmvw Update t)rans m)eans v)ars w)ghts    tmvw\n");
    printf(" -v f    Set minimum variance to f            0.0\n");
@@ -240,11 +244,14 @@
 int main(int argc, char *argv[])
 {
    char *datafn, *s;
+   LogFloat newP = 0.0;
    void Initialise1(void);
    void Initialise2(void);
    void LoadFile(char *fn);
+   void UpdateTheModel(void);
    void ReEstimateModel(void);
    void SaveModel(char *outfn);
+   void SaveDuration(void);
  
    if(InitShell(argc,argv,hrest_version,hrest_vc_id)<SUCCESS)
       HError(2200,"HRest: InitShell failed");
@@ -283,7 +290,7 @@
          segLab = GetStrArg();
          break;
       case 'm':
-         minSeg = GetChkedInt(1,1000,s); break;
+         minSeg = GetChkedInt(0,1000,s); break;
       case 't':
          segReject = FALSE;
          break;
@@ -296,6 +303,9 @@
       case 'o':
          outfn = GetStrArg();
          break;
+      case 'p':
+         parallel_mode = GetChkedInt(-1, 2000, s);
+         break;
       case 'w':
          mixWeightFloor = MINMIX * GetChkedFlt(0.0,100000.0,s); break;
       case 'B':
@@ -350,9 +360,38 @@
       if (NextArg()!=STRINGARG)
          HError(2219,"HRest: training data file name expected");
       datafn = GetStrArg();
-      LoadFile(datafn);
+      if (parallel_mode == 0) {
+         /* Load dumped accumulated stats. */
+         Source src = LoadAccs(&hset, datafn, uFlags);
+         float tmpFlt;
+         ReadFloat(&src, &tmpFlt, 1, ldBinary);
+         newP += tmpFlt;
+         int tmpInt;
+         ReadInt(&src, &tmpInt, 1, ldBinary);
+         nSeg += tmpInt;
+         if (calcDuration) {
+            DVector tmpVec = CreateDVector(&gstack, nStates - 2);
+            ReadInt(&src, &tmpInt, 1, ldBinary);
+            if (tmpInt != nStates) {
+               HError(9999, "HRest: Inconsistent number of states (%d vs %d)",
+                      tmpInt, nStates);
+            }
+            ReadDVector(&src, tmpVec, ldBinary);  /* Loads occ. */
+            int i;
+            for (i = 1; i < nStates - 1; ++i) durOcc[i] += tmpVec[i];
+            ReadDVector(&src, tmpVec, ldBinary);  /* Loads sum. */
+            for (i = 1; i < nStates - 1; ++i) durSum[i] += tmpVec[i];
+            ReadDVector(&src, tmpVec, ldBinary);  /* Loads sqr. */
+            for (i = 1; i < nStates - 1; ++i) durSqr[i] += tmpVec[i];
+         }
+         CloseSource(&src);
+      } else {
+         LoadFile(datafn);
+      }
    } while (NumArgs()>0);
-   nSeg = NumSegs(segStore);
+   if (parallel_mode != 0) {
+      nSeg = NumSegs(segStore);
+   }
    if (nSeg < minSeg)
       HError(2221,"HRest: Too Few Training Examples [%d]",nSeg);
    Initialise2();
@@ -361,10 +400,34 @@
              nSeg, maxT,minT);
       fflush(stdout);
    }
-   ReEstimateModel();
+   if (nSeg > 0) {
+      if (parallel_mode == 0) {
+         newP /= (float)(nSeg);
+         printf("Ave LogProb = %12.5f using %d examples\n", newP, nSeg);
+         fflush(stdout);
+         UpdateTheModel();
+      } else {
+         ReEstimateModel();
+      }
+   } else {
+      if (parallel_mode > 0) {
+         ReEstimateModel();
+      } else {
+         if (trace & T_TOP) {
+            printf("Bypassed parameter estimation.\n");
+            fflush(stdout);
+         }
+      }
+   }
 
-   if(SaveHMMSet(&hset,outDir,NULL,NULL,saveBinary)<SUCCESS)
-      HError(2211,"HRest: SaveHMMSet failed");
+   if (parallel_mode <= 0) {
+      if (SaveHMMSet(&hset, outDir, NULL, NULL, saveBinary) < SUCCESS) {
+         HError(2211, "HRest: SaveHMMSet failed");
+      }
+      if (calcDuration) {
+         SaveDuration();
+      }
+   }
 
    ResetUtil();
    ResetTrain();
@@ -446,6 +509,7 @@
    CreateHeap(&transStack,"TransStore", MSTAK, 1, 0.0, 1000, 1000);
    CreateHeap(&bufferStack,"BufferStore", MSTAK, 1, 0.0, 1000, 1000);
    AttachAccs(&hset, &accsStack, uFlags);
+   ZeroAccs(&hset, uFlags);
 
    SetVFloor( &hset, vFloor, minVar);
 
@@ -458,6 +522,14 @@
    for(s=1; s<=nStreams; s++)
       maxMixInS[s] = MaxMixInS(hmm, s);
    T = maxT = 0; minT = 100000;
+   if (calcDuration) {
+      durOcc = CreateDVector(&accsStack, nStates - 2);
+      durSum = CreateDVector(&accsStack, nStates - 2);
+      durSqr = CreateDVector(&accsStack, nStates - 2);
+      ZeroDVector(durOcc);
+      ZeroDVector(durSum);
+      ZeroDVector(durSqr);
+   }
 }
 
 /* Initialise2: 2nd phase of init after loading dbase */
@@ -465,6 +537,10 @@
 {
    int t,j,m,s;
 
+   occr = CreateVector(&gstack, nStates - 1);
+   zot = CreateVector(&gstack, hset.vecSize);
+
+   if (maxT == 0) return;
    alpha = CreateDMatrix(&alphaBetaStack,nStates,maxT);
    beta = CreateDMatrix(&alphaBetaStack,nStates,maxT);
    outprob = CreateMatrix(&alphaBetaStack,nStates-1,maxT); /* row 1 not used */
@@ -494,14 +570,6 @@
             stroutp[t][j] = CreateVector(&alphaBetaStack,nStreams);
       }
    }
-   occr = CreateVector(&gstack,nStates-1);
-   zot = CreateVector(&gstack,hset.vecSize);
-   
-   if (calcDuration) {
-      durOcc = CreateDVector(&accsStack, nStates);
-      durSum = CreateDVector(&accsStack, nStates);
-      durSqr = CreateDVector(&accsStack, nStates);
-   }
 }
 
 /* ---------------------------- Load Data ------------------------- */
@@ -531,7 +599,7 @@
    SetStreamWidths(info->tgtPK,info->tgtVecSize,hset.swidth,&eSep);
    obs = MakeObservation(&gstack,hset.swidth,info->tgtPK,
                          ((hset.hsKind==DISCRETEHS) ? TRUE:FALSE),eSep);
-   segStore = CreateSegStore(&segmentStack,obs,10);
+   segStore = CreateSegStore(&segmentStack,obs,10000);
    firstTime = FALSE;
 }
 
@@ -549,7 +617,7 @@
    LLink p;
    Observation obs;
 
-   if((pbuf=OpenBuffer(&bufferStack, fn, 10, dff, FALSE_dup, FALSE_dup))==NULL)
+   if((pbuf=OpenBuffer(&bufferStack, fn, 0, dff, FALSE_dup, FALSE_dup))==NULL)
       HError(2250,"LoadFile: Config parameters invalid");
    GetBufferInfo(pbuf,&info);
    CheckData(fn,info);
@@ -1128,11 +1196,13 @@
                x = x+Sumx-pr;
                   
                /* update statistics */
-               if (x>LSMALL) {
-                  durSqr[j-1] = LAdd(durSqr[j-1], x+2*log(t1-t0+1)); 
-                  durSum[j-1] = LAdd(durSum[j-1], x+log(t1-t0+1)); 
-                  durOcc[j-1] = LAdd(durOcc[j-1], x);
-               }      
+               if (x > MINEARG) {
+                  double dur = (double)(t1 - t0 + 1);
+                  double Lr = exp(x);
+                  durSqr[j - 1] += Lr * dur * dur;
+                  durSum[j - 1] += Lr * dur;
+                  durOcc[j - 1] += Lr;
+               }
             } 
             else 
                break; 
@@ -1469,7 +1539,7 @@
    for (i=1; i<=nStates-2; i++)
       fprintf(fp," 1");
    fprintf(fp,"\n<MSDINFO> %d", nStates-2);
-   for (i=1; i<=nStates-2; i++)
+   for (i=1; i<nStates; i++)
       fprintf(fp," 0");
    fprintf(fp,"\n<VECSIZE> %d <NULLD><DIAGC><%s>\n",nStates-2,ParmKind2Str(hset.pkind,buf));
    fprintf(fp,"~h \"%s\"\n",hmmId->name);
@@ -1480,18 +1550,20 @@
       fprintf(fp,"<STREAM> %d\n", i-1);
       
       /* mean */
-      if (durOcc[i-1]<=LSMALL) mean = 0;
-      else mean = L2F(durSum[i-1]-durOcc[i-1]);
+      if (durOcc[i-1]<=0.0) mean = 0;
+      else mean = (float)(durSum[i-1] / durOcc[i-1]);
       fprintf(fp,"<MEAN> 1\n");
       fprintf(fp," %e\n",mean);
       
       /* variance */
-      if ( (durOcc[i-1]<=LSMALL) 
-           ||(durSqr[i-1]-durOcc[i-1]<2*(durSum[i-1]-durOcc[i-1])) )
+      if ((durOcc[i - 1] <= 0.0) ||
+          (durSqr[i - 1] / durOcc[i - 1] <=
+          (durSum[i - 1] * durSum[i - 1] / durOcc[i - 1] / durOcc[i - 1]))) {
          var = minVar;
-      else {
-         var = LSub(durSqr[i-1]-durOcc[i-1], 2*(durSum[i-1]-durOcc[i-1]));
-         var = L2F(var);
+      } else {
+         var = (float)(durSqr[i - 1] / durOcc[i - 1] -
+                       (durSum[i - 1] * durSum[i - 1] /
+                        durOcc[i - 1] / durOcc[i - 1]));
       }
       /* floor variance */
       if (var<minVar) var = minVar;
@@ -1524,10 +1596,6 @@
    do {        /*main re-est loop*/   
       ZeroAccs(&hset, uFlags); newP = 0.0; ++iteration;
       nTokUsed = 0;
-      if (calcDuration)
-         for (i=1;i<DVectorSize(durOcc);i++) 
-            durOcc[i] = durSum[i] = durSqr[i] = LZERO;
-      
       for (seg=1;seg<=nSeg;seg++) {
          T=SegLength(segStore,seg);
          SetOutP(seg);
@@ -1542,6 +1610,9 @@
             if (trace&T_TOP) 
                printf("Example %d skipped\n",seg);
       }
+      if (parallel_mode > 0) {
+         break;
+      }
       if (nTokUsed==0)
          HError(2226,"ReEstimateModel: No Usable Training Examples");
       UpdateTheModel();
@@ -1561,7 +1632,7 @@
    if (calcDuration) {
       nTokUsed = 0;
       for (i=1;i<DVectorSize(durOcc);i++) 
-         durOcc[i] = durSum[i] = durSqr[i] = LZERO;
+         durOcc[i] = durSum[i] = durSqr[i] = 0.0;
       
       for (seg=1;seg<=nSeg;seg++) {
          T=SegLength(segStore,seg);
@@ -1577,18 +1648,32 @@
             if (trace&T_TOP) 
                printf("Example %d skipped\n",seg);
       }
-      if (nTokUsed==0)
+      if (parallel_mode < 0 && nTokUsed==0)
          HError(2226,"ReEstimateModel: No Usable Training Examples");
-
-      SaveDuration();
    }
-   
-   if (trace&T_TOP) {
-      if (converged)
-         printf("Estimation converged at iteration %d\n",iteration);
-      else
-         printf("Estimation aborted at iteration %d\n",iteration);
-      fflush(stdout);
+   if (parallel_mode > 0) {
+      /* dump HMM accs */
+      char acc_base[MAXSTRLEN], accs_file[MAXFNAMELEN];
+      snprintf(acc_base, MAXSTRLEN, "%s$.acc", segLab);
+      MakeFN(acc_base, outDir, NULL, accs_file);
+      FILE *f = DumpAccs(&hset, accs_file, uFlags, parallel_mode);
+      WriteFloat(f, &newP, 1, ldBinary);
+      WriteInt(f, &nTokUsed, 1, ldBinary);
+      if (calcDuration) {
+         WriteInt(f, &nStates, 1, ldBinary);
+         WriteDVector(f, durOcc, ldBinary);
+         WriteDVector(f, durSum, ldBinary);
+         WriteDVector(f, durSqr, ldBinary);
+      }
+      fclose(f);
+   } else {
+      if (trace&T_TOP) {
+         if (converged)
+            printf("Estimation converged at iteration %d\n",iteration);
+         else
+            printf("Estimation aborted at iteration %d\n",iteration);
+         fflush(stdout);
+      }
    }
 }
 /* ----------------------------------------------------------- */

Follow-Ups
[hts-users:04330] Re: A patch to HTS from Google, Tóth Bálint Pál