目录
移植coremark & dhrystone要点
1. coremark
1.1 coremark 计算方法
计算的核心为下方的代码
start_time();
#if (MULTITHREAD > 1)
/* 多线程的情况 */
#else
/*单线程情况*/
iterate(&results[0]);
#endif
stop_time();
对于 iterate(&results[0]); 再追进去可以发现
void * iterate(void *pres)
{
ee_u32 i;
ee_u16 crc;
core_results *res = (core_results *)pres;
ee_u32 iterations = res->iterations;
res->crc = 0;
res->crclist = 0;
res->crcmatrix = 0;
res->crcstate = 0;
for (i = 0; i < iterations; i++)
{
crc = core_bench_list(res, 1);
res->crc = crcu16(crc, res->crc);
crc = core_bench_list(res, -1);
res->crc = crcu16(crc, res->crc);
if (i == 0)
res->crclist = res->crc;
}
return NULL;
}
而这里的iterations 会在results[0].iterations = get_seed_32(4);
函数中被赋值为ITERATIONS
,所以我们可以知道,其实coremark 就是获取了下面这些参数
- start_time();
- stop_time();
- iterations
然后通过下面的代码算出 循环次数÷时间
的结果,可以看下面的代码,用default_num_contexts * results[0].iterations / time_in_secs(total_time)
计算出了目标值。
但是实际我们看的分数是Iterations/Sec /MHZ
,即最后需要的结果是跑分/(你的时钟/1MHZ)
,例如我最后跑分是14,频率是5MHZ,那么我的实际结果是:14/(5/1) = 2.8 coremark/Mhz
/* and report results */
ee_printf("CoreMark Size : %lu\n", (long unsigned)results[0].size);
ee_printf("Total ticks : %lu\n", (long unsigned)total_time);
#if HAS_FLOAT
/* 有浮点的情况 */
#else
ee_printf("Total time (secs): %d\n", time_in_secs(total_time));
if (time_in_secs(total_time) > 0)
ee_printf("Iterations/Sec : %d\n",
default_num_contexts * results[0].iterations
/ time_in_secs(total_time));
#endif
if (time_in_secs(total_time) < 10)
{
ee_printf(
"ERROR! Must execute for at least 10 secs for a valid result!\n");
total_errors++;
}
ee_printf("Iterations : %lu\n",
(long unsigned)default_num_contexts * results[0].iterations);
ee_printf("Compiler version : %s\n", COMPILER_VERSION);
ee_printf("Compiler flags : %s\n", COMPILER_FLAGS);
1.2 coremark 移植方法
由1.1 我们就可以知道,其实coremark 就是跑个程序n 循环,然后计算一个 指令/时间/频率 这样的结果,所以我们移植只需要给出以下几个参数
-
时间获取方式,start_time() 和 stop_time()向里追,最后会有时间函数的实现,这里一般获取的都是cnt 数,需要结合,即忽略了周期。
-
CLOCKS_PER_SEC 这个宏定义改为你的时钟频率,第一点的获取了这段时间内增加的cnt值,这里有了时间周期,那么
time_in_secs(total_time)
这个函数就能够计算出执行当前的时间了。其实最后也是cnt 值/频率=时间
-
iterations ,结合时钟频率不同,需要保证coremark 跑10s 以上,即
time_in_secs(total_time)
计算出来的结果是10s 以上,按照实际的结果给一个值就可以了。 -
printf 的实现,需要根据实际情况注意是不是要加printf这个宏
//如果编译的时候加上了 -DHAS_PRINTF,那么这里就不会生效,但是还是代表了HAS_PRINTF #ifndef HAS_PRINTF #define HAS_PRINTF 1 #endif //由于coremark 都是使用的ee_printf,所以需要把ee_printf符号替换为printf #if HAS_PRINTF #define ee_printf printf #endif
以上就是移植的要点,需要哪些文件内容官网readme 有说,就不赘述了。
2. dhrystone
2.1 dhrystone 计算方式
和coremark 类似,dhrystone的主函数也是进行算 跑dhrystone 程序的时间,以推出来单位时间下跑dhrystone 的个数,再除以MHZ的话就可以推出来 再1MHZ的情况下,1秒能跑多少dhrystone 程序。
主题程序如下:
/***************/
/* Start timer */
/***************/
#ifdef TIMES
times (&time_info);
Begin_Time = (long) time_info.tms_utime;
#endif
#ifdef TIME
Begin_Time = time ( (long *) 0);
#endif
#ifdef MSC_CLOCK
Begin_Time = clock();
#endif
for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index)
{
Proc_5();
Proc_4();
/* Ch_1_Glob == 'A', Ch_2_Glob == 'B', Bool_Glob == true */
Int_1_Loc = 2;
Int_2_Loc = 3;
strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING");
Enum_Loc = Ident_2;
Bool_Glob = ! Func_2 (Str_1_Loc, Str_2_Loc);
/* Bool_Glob == 1 */
while (Int_1_Loc < Int_2_Loc) /* loop body executed once */
{
Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc;
/* Int_3_Loc == 7 */
Proc_7 (Int_1_Loc, Int_2_Loc, &Int_3_Loc);
/* Int_3_Loc == 7 */
Int_1_Loc += 1;
} /* while */
/* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
Proc_8 (Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc);
/* Int_Glob == 5 */
Proc_1 (Ptr_Glob);
for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index)
/* loop body executed twice */
{
if (Enum_Loc == Func_1 (Ch_Index, 'C'))
/* then, not executed */
{
Proc_6 (Ident_1, &Enum_Loc);
strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 3'RD STRING");
Int_2_Loc = Run_Index;
Int_Glob = Run_Index;
}
}
/* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
Int_2_Loc = Int_2_Loc * Int_1_Loc;
Int_1_Loc = Int_2_Loc / Int_3_Loc;
Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc;
/* Int_1_Loc == 1, Int_2_Loc == 13, Int_3_Loc == 7 */
Proc_2 (&Int_1_Loc);
/* Int_1_Loc == 5 */
} /* loop "for Run_Index" */
/**************/
/* Stop timer */
/**************/
#ifdef TIMES
times (&time_info);
End_Time = (long) time_info.tms_utime;
#endif
#ifdef TIME
End_Time = time ( (long *) 0);
#endif
#ifdef MSC_CLOCK
End_Time = clock();
#endif
以上就可以通过Begin_Time
和End_Time
获取运行程序的时间,在有以下的计算程序:
User_Time = End_Time - Begin_Time;
#ifdef TIME
/*User_Time 已经是具体时间计数了*/
Microseconds = (float) User_Time * Mic_secs_Per_Second
/ (float) Number_Of_Runs;
Dhrystones_Per_Second = (float) Number_Of_Runs / (float) User_Time;
#else
/*User_Time 是counter值*/
Microseconds = (float) User_Time * Mic_secs_Per_Second
/ ((float) HZ * ((float) Number_Of_Runs));
Dhrystones_Per_Second = ((float) HZ * (float) Number_Of_Runs)
/ (float) User_Time;
#endif
以user_time 是counter值为例:Dhrystones_Per_Second =Number_Of_Runs ÷ 时间 = Number_Of_Runs÷ (counter/频率)
,于是就有了上面的公式。
对于一般的DMIP_MHZ,上面的结果还需要再除以一个频率,因为是xMhz 跑的,不是1Mhz 跑的。即
DMIP_MHZ = Dhrystones_Per_Second ÷(频率/1Mhz)
例如 Dhrystones_Per_Second 为12,主频为5Mhz,那么结果就为12/5 = 2.4.
2.2 dhrystone 移植要点
理解了第一点,这里就比较简单,其实和coremark 一样。只需要做好以下两点就可以了:
- 提供时间基准,用于获取start time 和 end time ,一般为timer 的计数器。
- 提供pintf 函数的重定义,用于打印。
- 注意不要让计数器超过计数范围了。