gpt4 book ai didi

c++ - 为什么 std::chrono 在测量 OpenMP 并行化 for 循环和编译器优化的执行时间时不起作用?

转载 作者:行者123 更新时间:2023-11-28 01:14:02 25 4
gpt4 key购买 nike

我有一个简单的代码:

#include <iostream>
#include <chrono>

int main(int argc, char ** argv)
{
int I=0;
double time=0.0;
for(int i=0; i<10; ++i)
{
auto begin1=std::chrono::steady_clock::now();
#pragma omp parallel for simd
for(int j=0; j<1000000; ++j) I=j;
auto end1=std::chrono::steady_clock::now();
auto timei=std::chrono::duration_cast<std::chrono::milliseconds>(end1-begin1).count();
std::cout<<"time 1:"<<time<<std::endl;
time+=timei;
std::cout<<"time 2:"<<time<<std::endl;
}
return 0;
}

使用 g++ 5.3.1 和编译行:

cmake . -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++ -DCMAKE_CXX_FLAGS="-O2 -fopenmp"

但是输出是:

time 1:0
time 2:11
time 1:11
time 2:16
time 1:16
time 2:16
time 1:16
time 2:16
time 1:16
time 2:16
time 1:16
time 2:16
time 1:16
time 2:16
time 1:16
time 2:16
time 1:16
time 2:16
time 1:16
time 2:16

你看,我无法使用 std::chrono 正确测量执行时间!

为什么?到底是怎么回事?如何衡量执行时间?

这是针对“-O2”和“-O1”编译器优化标志。使用“-O0”一切正常。为什么?

同样的情况是当我使用 Intel 编译器 icpc 19.0.1.144 和编译行时:

cmake .-DCMAKE_C_COMPILER=icc -DCMAKE_CXX_COMPILER=icpc -DCMAKE_CXX_FLAGS="-march=native -mtune=native -O2 -ipo16 -mcmodel=large"

如果使用“-O2”和“-O1”编译器标志,时间测量不正确,但如果用“-O0”替换它们,std::chrono 工作正常。

坦白说,我很震惊。

但问题是一样的:为什么使用 std::chrono 的执行时间测量在这里不能与“-O1”和“-O2”一起正常工作,而与“O0”一起工作?以及如何正确测量这段代码的执行时间?

请让我更新代码示例:

#include <iostream>
#include <chrono>
#include <ctime>
#include <omp.h>

int array[10000000]{0};

int main(int argc, char ** argv)
{
clock_t t;
double time=0.0;
for(int i=0; i<10; ++i)
{
auto begin1=std::chrono::steady_clock::now();
t=clock();
#pragma omp parallel for simd
for(int j=0; j<1000000; ++j) array[j]=j;
auto end1=std::chrono::steady_clock::now();
auto timei=std::chrono::duration_cast<std::chrono::milliseconds>(end1-begin1).count();
std::cout<<"time 1:"<<time<<std::endl;
time+=timei;
std::cout<<"time 2:"<<time<<std::endl;
t=clock()-t;
printf(\nt%i=%f\n", i, (double)t/CLOCKS_PER_SEC);
}
return 0;
}

现在 std:chrono 计时器正确更新。但有时 std::clock 和 std::chrono 的结果会有很大差异。假设 std::chrono 更准确,应该使用它的计时。

因此,正如@Hamza 在下面回答的那样,编译器简单地丢弃了不执行任何操作的代码块。但是 Intel 和 g++ 编译器都没有警告我任何事情。

所以,为了将来,不要编写什么都不做的循环。编译器可能会简单地丢弃没有效果的代码段。

在我的完整代码中,我尝试比较 2 个函数的相对性能,返回相同的结果:1 - 返回内插表的值和 2 - 从公式计算它(公式是表点的近似值)。我的错误是我将结果写在临时堆栈变量的内部循环中,什么也没做。编译器把它扔掉了。我应该将内部循环中的值写入一个数组,或者以任何其他方式累积它们,简单地说,做一些有用的事情,编译器不会丢弃。

我是这么理解的

最佳答案

我的猜测是编译器简单地优化了你在循环中所做的事情,因为它认为它是无用的。使用以下代码,您可以获得一些实际的 ms:

#include <iostream>
#include <chrono>
#include <omp.h>

int main(int argc, char ** argv)
{
int I=0;
double time=0.0;
for(int i=0; i<10; ++i)
{
auto begin1=std::chrono::steady_clock::now();
#pragma omp parallel for simd
for(int j=0; j<100000000; ++j) I+=j;
auto end1=std::chrono::steady_clock::now();
auto timei=std::chrono::duration_cast<std::chrono::milliseconds>(end1- begin1).count();

std::cout << I << std::endl;
std::cout<<"time 1:"<<time<<std::endl;
time+=timei;
std::cout<<"time 2:"<<time<<std::endl;
}
return 0;
}

我得到以下输出:

887459712
time 1:0
time 2:71
1774919424
time 1:71
time 2:142
-1632588160
time 1:142
time 2:213
-745128448
time 1:213
time 2:283
142331264
time 1:283
time 2:351
1029790976
time 1:351
time 2:419
1917250688
time 1:419
time 2:487
-1490256896
time 1:487
time 2:555
-602797184
time 1:555
time 2:623
284662528
time 1:623
time 2:692

关于c++ - 为什么 std::chrono 在测量 OpenMP 并行化 for 循环和编译器优化的执行时间时不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59282686/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com