c - 如何在 Windows 10 中使用 Code::Blocks 16.01 计算 -O3 的时钟周期?

标签 c gcc codeblocks

在我的 C 程序中,我正在计算运行 Windows 10 家庭版的 64 位英特尔酷睿 i5-2410M Sandy Bridge 机器上的时钟周期数,但有一些奇怪的地方。我在发布版本中使用 Code::Blocks (CB) 16.01 在 -O2 和 -O3 编译程序。对于 -O2,时钟周期没问题,但 -O3 返回 0 个周期。目前,我没有考虑 turbo-boost 和超线程,但以后肯定会禁用它们。

我使用以下命令进行编译

mingw32-gcc.exe -Wall -O2 -m32 -IC:\GMP\include -c "E:\abc\main.c" -o obj\Release\main.o
mingw32-gcc.exe -Wall -O3 -m32 -IC:\GMP\include -c "E:\abc\main.c" -o obj\Release\main.o

我们有

void schoolbook_9(int32_t *X, int32_t *Y, int64_t *Z){
Z[0] = (int64_t)X[0]*Y[0]  + (int64_t)X[1]*Y[1]  + (int64_t)X[2]*Y[2]  + (int64_t)X[3]*Y[3] + (int64_t)X[4]*Y[4] + (int64_t)X[5]*Y[5] + (int64_t)X[6]*Y[6] + (int64_t)X[7]*Y[7] + (int64_t)X[8]*Y[8];
Z[1] = (int64_t)X[9]*Y[0]  + (int64_t)X[0]*Y[1]  + (int64_t)X[1]*Y[2]  + (int64_t)X[2]*Y[3] + (int64_t)X[3]*Y[4] + (int64_t)X[4]*Y[5] + (int64_t)X[5]*Y[6] + (int64_t)X[6]*Y[7] + (int64_t)X[7]*Y[8];
Z[2] = (int64_t)X[10]*Y[0] + (int64_t)X[9]*Y[1]  + (int64_t)X[0]*Y[2]  + (int64_t)X[1]*Y[3] + (int64_t)X[2]*Y[4] + (int64_t)X[3]*Y[5] + (int64_t)X[4]*Y[6] + (int64_t)X[5]*Y[7] + (int64_t)X[6]*Y[8];
Z[3] = (int64_t)X[11]*Y[0] + (int64_t)X[10]*Y[1] + (int64_t)X[9]*Y[2]  + (int64_t)X[0]*Y[3] + (int64_t)X[1]*Y[4] + (int64_t)X[2]*Y[5] + (int64_t)X[3]*Y[6] + (int64_t)X[4]*Y[7] + (int64_t)X[5]*Y[8];
Z[4] = (int64_t)X[12]*Y[0] + (int64_t)X[11]*Y[1] + (int64_t)X[10]*Y[2] + (int64_t)X[9]*Y[3] + (int64_t)X[0]*Y[4] + (int64_t)X[1]*Y[5] + (int64_t)X[2]*Y[6] + (int64_t)X[3]*Y[7] + (int64_t)X[4]*Y[8];
Z[5] = (int64_t)X[13]*Y[0] + (int64_t)X[12]*Y[1] + (int64_t)X[11]*Y[2] + (int64_t)X[10]*Y[3] + (int64_t)X[9]*Y[4] + (int64_t)X[0]*Y[5] + (int64_t)X[1]*Y[6] + (int64_t)X[2]*Y[7] + (int64_t)X[3]*Y[8];
Z[6] = (int64_t)X[14]*Y[0] + (int64_t)X[13]*Y[1] + (int64_t)X[12]*Y[2] + (int64_t)X[11]*Y[3] + (int64_t)X[10]*Y[4] + (int64_t)X[9]*Y[5] + (int64_t)X[0]*Y[6] + (int64_t)X[1]*Y[7] + (int64_t)X[2]*Y[8];
Z[7] = (int64_t)X[15]*Y[0] + (int64_t)X[14]*Y[1] + (int64_t)X[13]*Y[2] + (int64_t)X[12]*Y[3] + (int64_t)X[11]*Y[4] + (int64_t)X[10]*Y[5] + (int64_t)X[9]*Y[6] + (int64_t)X[0]*Y[7] + (int64_t)X[1]*Y[8];
Z[8] = (int64_t)X[16]*Y[0] + (int64_t)X[15]*Y[1] + (int64_t)X[14]*Y[2] + (int64_t)X[13]*Y[3] + (int64_t)X[12]*Y[4] + (int64_t)X[11]*Y[5] + (int64_t)X[10]*Y[6] + (int64_t)X[9]*Y[7] + (int64_t)X[0]*Y[8];}

我按如下方式计算时钟周期

int32_t X[17], Y[9];
int64_t Z[9];
utype64 start, end;
uint32_t i;

srand(time(NULL));
for(i=0; i<17; i++)
    X[i] = rand()%(uint32_t)pow(2.0, 29);
srand(time(NULL));
for(i=0; i<9; i++)
    Y[i] = rand()%(uint32_t)pow(2.0, 29);

start=rdtsc();
end=rdtscp();
start=rdtsc();
for(i=0; i<10000000; i++)
    schoolbook_9(X, Y, Z);

end=rdtscp();
printf("\n%s%"PRIu64"\n", "The cycles count using SB of size 9 is :: ", (end-start)/10000000);

我正在使用 rdtscp 指令,因为我的系统支持它,可能它在 32 位机器上不可用,因此,我已经使用/不使用 rdtscp 测试了我的程序。参数 X、Y 和 Z 是数组,其中 X 和 Y 是 32 位,Z 是 64 位。

那么,我的问题是如何获得 -O3 的循环数?因为对于当前代码,我得到 0 个周期。

标记 -ftree-loop-vectorize 设置为 -O3,如本页所述 https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html .这是否意味着循环已被矢量化?如果是,那么如何确定 vector 的长度(4 个元素、6 个元素等)?

最佳答案

这是因为 end - start 小于 10000000-O3。您的部门生产 0

utype64 result = end - start;
utype64 cycle = 10000000;
utype64 total = result / cycle;
utype64 rest = result % cycle;
printf("The cycles count using SB of size 9 is " PRIu64
       " and the rest is " PRIu64 "\n",
       total, rest);

而且你不应该调用两次 srand(time(NULL));。它是无用的,并且会产生奇怪的行为。

注意:我无法测试自己。

关于c - 如何在 Windows 10 中使用 Code::Blocks 16.01 计算 -O3 的时钟周期?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41358925/

相关文章:

c++ - 如何关闭 Code::Blocks 的自动完成

C结构还是函数?

gcc - 使用未对齐的缓冲区进行矢量化 : using VMASKMOVPS: generating a mask from a misalignment count? 或者根本不使用该 insn

c - 尝试更改变量值时发生总线错误

对 C 中的 GCC 和 scanf 感到困惑

linux - AWS : C compiler on EC2 not working when using Elastic Beanstalk container_commands

Python空闲。自动完成/显示完成不起作用

c++ - 将 char 类型转换为字符串时,代码始终返回 255 或 -1073741819

c - 在 Minix 中 fork 后执行 mkdir 后创建的奇怪目录(USER=root)

c - 绑定(bind)时间和C赋值语句