BENCH_INNER:lmbench3.0 src代码macros查询

我正在阅读lmbench的创造者MHZ – Benchmark论文解剖学,并在源代码旁边浏览代码。

  1. 该文件可以下载@ MHz:Microbenchmark解剖学
  2. 由Carl Staelin和Larry McVoy撰写的源代码lmbench-3.0

在BENCH_INNER()macros里面,我有一个疑问:

#define BENCH_INNER(loop_body, enough) { \ static iter_t __iterations = 1; \ int __enough = get_enough(enough); \ iter_t __n; \ double __result = 0.; \ \ while(__result < 0.95 * __enough) { \ start(0); \ for (__n = __iterations; __n > 0; __n--) { \ loop_body; \ } \ __result = stop(0,0); \ if (__result < 0.99 * __enough \ || __result > 1.2 * __enough) { \ if (__result > 150.) { \ double tmp = __iterations / __result; \ tmp *= 1.1 * __enough; \ __iterations = (iter_t)(tmp + 1); \ } else { \ if (__iterations > (iter_t)1<<27) { \ __result = 0.; \ break; \ } \ __iterations <<= 3; \ } \ } \ } /* while */ \ save_n((uint64)__iterations); settime((uint64)__result); \ } 
  1. 根据我的理解,BENCH_INNER用于自动计算所选时间间隔('足够')的最佳迭代次数。 循环执行直到我们不断迭代一段代码“loop_body”,这个代码至less需要95%的时间间隔,从5ms到1s。

  2. 为了简单起见,让我们把'足够'为10000微秒

  3. 我们以__iterations = 1开始
  4. 随着时间的推移,我们达到了__result> 1.2 *'足够'的阶段,即__result> 12000微秒
  5. 现在,因为__result> 150微秒,所以我们继续扩展__iterations的值,以使__result大约等于1.1 *'足够'
  6. 但是在我们可以重新计算__result之前,我们会打破这个循环,因为之前的__result> .95 *'够了'
  7. 我们继续并保存__result的值和修改后的值__iterations(这里__result的值不是我们保存的__iterations)

这种情况下的代码不应该重新计算__result吗? 我错过了一些基本的东西?

是的,这里有一个问题,__result必须设置为零。

在代码中我还能看到另外一个可能的问题 – 结果是在一种情况下0.99*enough0.99*enough进行比较,而在另外一种情况下0.95*enough0.95*enough进行比较,这是高度可疑的错字。 我建议你重写这个宏,明确说明“令人满意”的条件,并简化逻辑,首先检查良好的条件。 喜欢这个:

 #define SEARCH_EXIT_CASE(__result, __enough) ((__result) > 0.95 * (__enough) && (__result) < 1.2 * (__enough)) #define BENCH_INNER(loop_body, enough) { \ static iter_t __iterations = 1; \ int __enough = get_enough(enough); \ iter_t __n; \ double __result = 0.; \ \ while(!SEARCH_EXIT_CASE(__result, __enough)) { \ start(0); \ for (__n = __iterations; __n > 0; __n--) { \ loop_body; \ } \ __result = stop(0,0); \ /* good result */ \ if (SEARCH_EXIT_CASE(__result, __enough)) { \ break; \ } \ /* failure cases */ \ if (__result > 150.) { \ double tmp = __iterations / __result; \ tmp *= 1.1 * __enough; \ __iterations = (iter_t)(tmp + 1); \ } else { \ if (__iterations > (iter_t)1<<27) { \ __result = 0.; \ break; \ } \ __iterations <<= 3; \ } \ __result = 0.; \ } /* while */ \ save_n((uint64)__iterations); settime((uint64)__result); \ } 

另外我建议定义像1<<27, 1.1, 3, 150.0 RESULT_OVERFLOW这样的其他魔法常数1<<27, 1.1, 3, 150.0使其具有像MAX_ITERCORRECTION_RATEINCREASE_RATERESULT_OVERFLOW等有意义的名称。