From 7f1b897bee23650e1e3e9e9c0dbf58608adac178 Mon Sep 17 00:00:00 2001 From: Vincent Rabaud Date: Fri, 19 Aug 2016 14:32:56 +0200 Subject: [PATCH] Faster stochastic histogram merging. Constants are such that brute force is sometimes faster for some data (mostly big images it seems). Change-Id: I90aef536408683535e3b09ddfa2e77a9834038f6 --- src/enc/histogram.c | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/src/enc/histogram.c b/src/enc/histogram.c index 229b82fb..99bfbde5 100644 --- a/src/enc/histogram.c +++ b/src/enc/histogram.c @@ -737,6 +737,8 @@ static void HistogramCombineStochastic(VP8LHistogramSet* const image_histo, const int outer_iters = image_histo_size * iter_mult; const int num_pairs = image_histo_size / 2; const int num_tries_no_success = outer_iters / 2; + int idx2_max = image_histo_size - 1; + int do_brute_dorce = 0; VP8LHistogram** const histograms = image_histo->histograms; // Collapse similar histograms in 'image_histo'. @@ -747,43 +749,62 @@ static void HistogramCombineStochastic(VP8LHistogramSet* const image_histo, double best_cost_diff = 0.; int best_idx1 = -1, best_idx2 = 1; int j; - const int num_tries = + int num_tries = (num_pairs < image_histo_size) ? num_pairs : image_histo_size; + // Use a brute force approach if: + // - stochastic has not worked for a while and + // - if the number of iterations for brute force is less than the number of + // iterations if we never find a match ever again stochastically (hence + // num_tries times the number of remaining outer iterations). + do_brute_dorce = + (tries_with_no_success > 10) && + (idx2_max * (idx2_max + 1) < 2 * num_tries * (outer_iters - iter)); + if (do_brute_dorce) num_tries = idx2_max; + seed += iter; for (j = 0; j < num_tries; ++j) { double curr_cost_diff; // Choose two histograms at random and try to combine them. - const uint32_t idx1 = MyRand(&seed) % image_histo_size; - const uint32_t tmp = (j & 7) + 1; - const uint32_t diff = - (tmp < 3) ? tmp : MyRand(&seed) % (image_histo_size - 1); - const uint32_t idx2 = (idx1 + diff + 1) % image_histo_size; - if (idx1 == idx2) { - continue; + uint32_t idx1, idx2; + if (do_brute_dorce) { + // Use a brute force approach. + idx1 = (uint32_t)j; + idx2 = (uint32_t)idx2_max; + } else { + const uint32_t tmp = (j & 7) + 1; + const uint32_t diff = + (tmp < 3) ? tmp : MyRand(&seed) % (image_histo_size - 1); + idx1 = MyRand(&seed) % image_histo_size; + idx2 = (idx1 + diff + 1) % image_histo_size; + if (idx1 == idx2) { + continue; + } } // Calculate cost reduction on combining. curr_cost_diff = HistogramAddEval(histograms[idx1], histograms[idx2], tmp_histo, best_cost_diff); - if (curr_cost_diff < best_cost_diff) { // found a better pair? + if (curr_cost_diff < best_cost_diff) { // found a better pair? HistogramSwap(&best_combo, &tmp_histo); best_cost_diff = curr_cost_diff; best_idx1 = idx1; best_idx2 = idx2; } } + if (do_brute_dorce) --idx2_max; if (best_idx1 >= 0) { HistogramSwap(&best_combo, &histograms[best_idx1]); // swap best_idx2 slot with last one (which is now unused) --image_histo_size; + if (idx2_max >= image_histo_size) idx2_max = image_histo_size - 1; if (best_idx2 != image_histo_size) { HistogramSwap(&histograms[image_histo_size], &histograms[best_idx2]); histograms[image_histo_size] = NULL; } tries_with_no_success = 0; } - if (++tries_with_no_success >= num_tries_no_success) { + if (++tries_with_no_success >= num_tries_no_success || idx2_max == 0) { break; } }