in cpc/compression_characterization.go [132:314]
func (cc *CompressionCharacterization) doTrialsAtLgKAtN(lgK int, n int64, totalTrials int) error {
k := 1 << lgK
minNK := k
if int64(k) > n {
minNK = int(n)
}
nOverK := float64(n) / float64(k)
lgTotTrials := bits.TrailingZeros32(uint32(totalTrials))
// We'll define waves = 2^(lgWaves). Each wave has trialsPerWave = 2^(lgTotTrials - lgWaves).
lgWaves := lgTotTrials - 10
if lgWaves < 0 {
lgWaves = 0
}
trialsPerWave := 1 << (lgTotTrials - lgWaves)
wavesCount := 1 << lgWaves
streamSketches := make([]*CpcSketch, trialsPerWave)
compressedStates1 := make([]*CpcCompressedState, trialsPerWave)
memoryArr := make([][]byte, trialsPerWave)
compressedStates2 := make([]*CpcCompressedState, trialsPerWave)
unCompressedSketches := make([]*CpcSketch, trialsPerWave)
var totalC, totalW int64
var sumCtorNS, sumUpdNS, sumComNS, sumSerNS, sumDesNS, sumUncNS, sumEquNS int64
startTime := time.Now()
// wave loop
for w := 0; w < wavesCount; w++ {
// Construct sketches
nanoStart := time.Now().UnixNano()
for t := 0; t < trialsPerWave; t++ {
sketch, err := NewCpcSketch(lgK, internal.DEFAULT_UPDATE_SEED)
if err != nil {
return err
}
streamSketches[t] = sketch
}
nanoEnd := time.Now().UnixNano()
sumCtorNS += nanoEnd - nanoStart
nanoStart = nanoEnd
// Update each sketch
for t := 0; t < trialsPerWave; t++ {
sketch := streamSketches[t]
for i := int64(0); i < n; i++ {
cc.vIn += common.InverseGoldenU64
_ = sketch.UpdateUint64(cc.vIn)
}
}
nanoEnd = time.Now().UnixNano()
sumUpdNS += nanoEnd - nanoStart
nanoStart = nanoEnd
// Compress each sketch
for t := 0; t < trialsPerWave; t++ {
sketch := streamSketches[t]
state, err := NewCpcCompressedStateFromSketch(sketch)
if err != nil {
panic(fmt.Sprintf("Compression error: %v", err))
}
compressedStates1[t] = state
totalC += int64(sketch.numCoupons)
// approximate measure of total words in CSV + CW
totalW += int64(state.CsvLengthInts + state.CwLengthInts)
}
nanoEnd = time.Now().UnixNano()
sumComNS += nanoEnd - nanoStart
nanoStart = nanoEnd
// Convert each CompressedState to a byte slice
for t := 0; t < trialsPerWave; t++ {
state := compressedStates1[t]
mem, err := state.exportToMemory()
if err != nil {
panic(fmt.Sprintf("exportToMemory error: %v", err))
}
memoryArr[t] = mem
}
nanoEnd = time.Now().UnixNano()
sumSerNS += nanoEnd - nanoStart
nanoStart = nanoEnd
// Import from memory to new CompressedState
for t := 0; t < trialsPerWave; t++ {
mem := memoryArr[t]
state, err := importFromMemory(mem)
if err != nil {
panic(fmt.Sprintf("importFromMemory error: %v", err))
}
compressedStates2[t] = state
}
nanoEnd = time.Now().UnixNano()
sumDesNS += nanoEnd - nanoStart
nanoStart = nanoEnd
// Uncompress into a new CpcSketch
for t := 0; t < trialsPerWave; t++ {
state := compressedStates2[t]
uncSk, err := uncompressSketch(state, internal.DEFAULT_UPDATE_SEED)
if err != nil {
return err
}
unCompressedSketches[t] = uncSk
}
nanoEnd = time.Now().UnixNano()
sumUncNS += nanoEnd - nanoStart
nanoStart = nanoEnd
// Equality check
for t := 0; t < trialsPerWave; t++ {
s1 := streamSketches[t]
s2 := unCompressedSketches[t]
if !specialEquals(s1, s2, false, false) {
return fmt.Errorf("uncompressed sketch not equal to original")
}
}
nanoEnd = time.Now().UnixNano()
sumEquNS += nanoEnd - nanoStart
nanoStart = nanoEnd
}
totalSeconds := time.Since(startTime).Seconds()
avgC := float64(totalC) / float64(totalTrials)
avgCoK := avgC / float64(k)
avgWords := float64(totalW) / float64(totalTrials)
avgBytes := 4.0 * avgWords // 4 bytes per int
// compute average times
// Each sum is total for all waves, so we divide by totalTrials
avgCtor := float64(sumCtorNS) / float64(totalTrials)
avgUpd := float64(sumUpdNS) / float64(totalTrials)
avgCom := float64(sumComNS) / float64(totalTrials)
avgSer := float64(sumSerNS) / float64(totalTrials)
avgDes := float64(sumDesNS) / float64(totalTrials)
avgUnc := float64(sumUncNS) / float64(totalTrials)
avgEqu := float64(sumEquNS) / float64(totalTrials)
avgUpdPerN := avgUpd / float64(n)
avgComPer2C := avgCom / (2.0 * avgC)
avgComPerK := avgCom / float64(k)
avgSerPerW := avgSer / avgWords
avgDesPerW := avgDes / avgWords
avgUncPer2C := avgUnc / (2.0 * avgC)
avgUncPerK := avgUnc / float64(k)
avgEquPerMinNK := avgEqu / float64(minNK)
// final flavor/offset from last wave
lastSketch := unCompressedSketches[len(unCompressedSketches)-1]
finFlavor := lastSketch.getFlavor()
finOff := lastSketch.windowOffset
flavorOff := fmt.Sprintf("%s%2d", finFlavor.String(), finOff)
// Print final line
cc.printf(
cc.dfmt,
lgK,
totalTrials,
n,
minNK,
avgCoK,
flavorOff,
nOverK,
avgBytes,
avgCtor,
avgUpd,
avgCom,
avgSer,
avgDes,
avgUnc,
avgEqu,
avgUpdPerN,
avgComPer2C,
avgComPerK,
avgSerPerW,
avgDesPerW,
avgUncPer2C,
avgUncPerK,
avgEquPerMinNK,
totalSeconds,
)
return nil
}