在 C 中的循环中获取特定代码部分的时间
Getting the Timing of a Specific Part of Code in a Loop in C
问题描述
下面我有一个程序正在执行两个简单的加法和乘法运算。然后我将这两个简单操作的总和存储在两个分别称为 total1 和 total2 的变量中。就计算而言,total2 将需要更多时间才能完全执行。我实现代码的方式,我目前正在对两个数学运算的整个模拟进行计时。
问题
是否可以单独计时total1和total 2的最终结果?我这样问是因为我想单独获取total1和total2的具体时间
任务目的
我完全知道 long long 在内存方面很昂贵,并不是节省内存的最有效方法。此代码和问题的唯一目的是计时而不是代码优化。
C代码
#include <stdio.h>
#include <time.h>
int main()
{
long long total1 = 0, total2 = 0, i = 0;
double simulation_time = 0;
clock_t Start = clock();
do
{
total1 += i + i;
total2 += i * i * i * i;
i++;
} while (i < 1000000000);
clock_t End = clock();
printf("Total 1 = %u \n", total1);
printf("Total 2 = %u \n", total2);
simulation_time = (double)(End - Start) / CLOCKS_PER_SEC;
printf("Runtime of Whole Simulation using clock_t: %f\n", simulation_time);
return 0;
}
我不确定我是否理解您的问题,但是要分别为每个操作计时,您只需进行两个单独的循环即可。
#include <stdio.h>
#include <time.h>
int main()
{
long long total1 = 0, total2 = 0, i = 0, j = 1000000000;
double simulation_time1, simulation_time2;
clock_t Start, End;
/* addition */
Start = clock();
do
{
total1 += i + i;
i++;
} while (i < j);
End = clock();
simulation_time1 = (double)(End - Start) / CLOCKS_PER_SEC;
/* multiplication */
Start = clock();
do
{
total2 += i * i * i * i;
i++;
} while (i < j);
End = clock();
simulation_time2 = (double)(End - Start) / CLOCKS_PER_SEC;
printf("Total 1 = %u \n", total1);
printf("Total 2 = %u \n", total2);
printf("Runtime of Whole Simulation: %f\n"
"Runtime of Addition: %f\n"
"Runtime of Multiplication: %f\n",
simulation_time1 + simulation_time2,
simulation_time1, simulation_time2);
return 0;
}
您有两个操作要分别计时。一是累积i+i
,二是累积i*i*i*i
.
我假设您在 x86-64 上使用 GCC -O2
。
如果我们注释掉total2
,计算total1
生成的程序集是:
movabs rdx, 999999999000000000
聪明的编译器!它在编译时完成整个计算。所以那所花费的时间基本为零。
如果我们改为注释掉 total1
,用于计算 total2
的循环程序集是:
.L2:
mov rdx, rax
imul rdx, rax ; i squared
add rax, 1
imul rdx, rdx ; i squared squared
add rsi, rdx ; accumulate
cmp rax, 1000000000 ; loop condition
jne .L2
我们可以参考 Agner Fog 的指令表,而不是尝试对单行代码进行微基准测试:http://www.agner.org/optimize/instruction_tables.pdf
假设您使用的是 Intel Haswell,并手动进行一些端口分配,表格告诉我们:
.L2: ; ports cycles latency
mov rdx, rax ; p0 0.25 1
imul rdx, rax ; p1 1 3
add rax, 1 ; p0 0.25 1
imul rdx, rdx ; p1 1 3
add rsi, rdx ; p0 0.25 1
cmp rax, 1000000000 ; p5 0.25 1
jne .L2 ; p6 1-2
其中一些指令可能会重叠,因此每次迭代大约需要 3-4 个核心周期。在 3-4 GHz 处理器上,执行 10 亿次循环迭代大约需要 1 秒。
问题描述
下面我有一个程序正在执行两个简单的加法和乘法运算。然后我将这两个简单操作的总和存储在两个分别称为 total1 和 total2 的变量中。就计算而言,total2 将需要更多时间才能完全执行。我实现代码的方式,我目前正在对两个数学运算的整个模拟进行计时。
问题
是否可以单独计时total1和total 2的最终结果?我这样问是因为我想单独获取total1和total2的具体时间
任务目的
我完全知道 long long 在内存方面很昂贵,并不是节省内存的最有效方法。此代码和问题的唯一目的是计时而不是代码优化。
C代码
#include <stdio.h>
#include <time.h>
int main()
{
long long total1 = 0, total2 = 0, i = 0;
double simulation_time = 0;
clock_t Start = clock();
do
{
total1 += i + i;
total2 += i * i * i * i;
i++;
} while (i < 1000000000);
clock_t End = clock();
printf("Total 1 = %u \n", total1);
printf("Total 2 = %u \n", total2);
simulation_time = (double)(End - Start) / CLOCKS_PER_SEC;
printf("Runtime of Whole Simulation using clock_t: %f\n", simulation_time);
return 0;
}
我不确定我是否理解您的问题,但是要分别为每个操作计时,您只需进行两个单独的循环即可。
#include <stdio.h>
#include <time.h>
int main()
{
long long total1 = 0, total2 = 0, i = 0, j = 1000000000;
double simulation_time1, simulation_time2;
clock_t Start, End;
/* addition */
Start = clock();
do
{
total1 += i + i;
i++;
} while (i < j);
End = clock();
simulation_time1 = (double)(End - Start) / CLOCKS_PER_SEC;
/* multiplication */
Start = clock();
do
{
total2 += i * i * i * i;
i++;
} while (i < j);
End = clock();
simulation_time2 = (double)(End - Start) / CLOCKS_PER_SEC;
printf("Total 1 = %u \n", total1);
printf("Total 2 = %u \n", total2);
printf("Runtime of Whole Simulation: %f\n"
"Runtime of Addition: %f\n"
"Runtime of Multiplication: %f\n",
simulation_time1 + simulation_time2,
simulation_time1, simulation_time2);
return 0;
}
您有两个操作要分别计时。一是累积i+i
,二是累积i*i*i*i
.
我假设您在 x86-64 上使用 GCC -O2
。
如果我们注释掉total2
,计算total1
生成的程序集是:
movabs rdx, 999999999000000000
聪明的编译器!它在编译时完成整个计算。所以那所花费的时间基本为零。
如果我们改为注释掉 total1
,用于计算 total2
的循环程序集是:
.L2:
mov rdx, rax
imul rdx, rax ; i squared
add rax, 1
imul rdx, rdx ; i squared squared
add rsi, rdx ; accumulate
cmp rax, 1000000000 ; loop condition
jne .L2
我们可以参考 Agner Fog 的指令表,而不是尝试对单行代码进行微基准测试:http://www.agner.org/optimize/instruction_tables.pdf
假设您使用的是 Intel Haswell,并手动进行一些端口分配,表格告诉我们:
.L2: ; ports cycles latency
mov rdx, rax ; p0 0.25 1
imul rdx, rax ; p1 1 3
add rax, 1 ; p0 0.25 1
imul rdx, rdx ; p1 1 3
add rsi, rdx ; p0 0.25 1
cmp rax, 1000000000 ; p5 0.25 1
jne .L2 ; p6 1-2
其中一些指令可能会重叠,因此每次迭代大约需要 3-4 个核心周期。在 3-4 GHz 处理器上,执行 10 亿次循环迭代大约需要 1 秒。