Faster stochastic histogram merging.

Constants are such that brute force is sometimes faster for some
data (mostly big images it seems).

Change-Id: I90aef536408683535e3b09ddfa2e77a9834038f6
This commit is contained in:
Vincent Rabaud 2016-08-19 14:32:56 +02:00
parent 48c810b85c
commit 7f1b897bee

View File

@ -737,6 +737,8 @@ static void HistogramCombineStochastic(VP8LHistogramSet* const image_histo,
const int outer_iters = image_histo_size * iter_mult; const int outer_iters = image_histo_size * iter_mult;
const int num_pairs = image_histo_size / 2; const int num_pairs = image_histo_size / 2;
const int num_tries_no_success = outer_iters / 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; VP8LHistogram** const histograms = image_histo->histograms;
// Collapse similar histograms in 'image_histo'. // Collapse similar histograms in 'image_histo'.
@ -747,43 +749,62 @@ static void HistogramCombineStochastic(VP8LHistogramSet* const image_histo,
double best_cost_diff = 0.; double best_cost_diff = 0.;
int best_idx1 = -1, best_idx2 = 1; int best_idx1 = -1, best_idx2 = 1;
int j; int j;
const int num_tries = int num_tries =
(num_pairs < image_histo_size) ? num_pairs : image_histo_size; (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; seed += iter;
for (j = 0; j < num_tries; ++j) { for (j = 0; j < num_tries; ++j) {
double curr_cost_diff; double curr_cost_diff;
// Choose two histograms at random and try to combine them. // Choose two histograms at random and try to combine them.
const uint32_t idx1 = MyRand(&seed) % image_histo_size; uint32_t idx1, idx2;
const uint32_t tmp = (j & 7) + 1; if (do_brute_dorce) {
const uint32_t diff = // Use a brute force approach.
(tmp < 3) ? tmp : MyRand(&seed) % (image_histo_size - 1); idx1 = (uint32_t)j;
const uint32_t idx2 = (idx1 + diff + 1) % image_histo_size; idx2 = (uint32_t)idx2_max;
if (idx1 == idx2) { } else {
continue; 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. // Calculate cost reduction on combining.
curr_cost_diff = HistogramAddEval(histograms[idx1], histograms[idx2], curr_cost_diff = HistogramAddEval(histograms[idx1], histograms[idx2],
tmp_histo, best_cost_diff); 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); HistogramSwap(&best_combo, &tmp_histo);
best_cost_diff = curr_cost_diff; best_cost_diff = curr_cost_diff;
best_idx1 = idx1; best_idx1 = idx1;
best_idx2 = idx2; best_idx2 = idx2;
} }
} }
if (do_brute_dorce) --idx2_max;
if (best_idx1 >= 0) { if (best_idx1 >= 0) {
HistogramSwap(&best_combo, &histograms[best_idx1]); HistogramSwap(&best_combo, &histograms[best_idx1]);
// swap best_idx2 slot with last one (which is now unused) // swap best_idx2 slot with last one (which is now unused)
--image_histo_size; --image_histo_size;
if (idx2_max >= image_histo_size) idx2_max = image_histo_size - 1;
if (best_idx2 != image_histo_size) { if (best_idx2 != image_histo_size) {
HistogramSwap(&histograms[image_histo_size], &histograms[best_idx2]); HistogramSwap(&histograms[image_histo_size], &histograms[best_idx2]);
histograms[image_histo_size] = NULL; histograms[image_histo_size] = NULL;
} }
tries_with_no_success = 0; 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; break;
} }
} }