一个足够大的问题大小 C++ 需要 0 个运行时间

a large enough problemSize in C++ takes 0 run time

本文关键字:C++ 需要 运行时间 问题 一个      更新时间:2023-10-16

这段用于演示算法复杂性和测量算法运行时间的代码来自一本书 PYTHON基础:从第一个程序到数据结构

"""
File: timing1.py
Prints the running times for problem sizes that double,
using a single loop.
"""
import time
problemSize = 10000000
print "%12s%16s" % ("Problem Size", "Seconds")
for count in xrange(5):
start = time.time()
# The start of the algorithm
work = 1
for x in xrange(problemSize):
work += 1
work -= 1
# The end of the algorithm
elapsed = time.time() - start
print "%12d%16.3f" % (problemSize, elapsed)
problemSize *= 2

这段代码运行良好,我正在尝试与C++进行类似的试验。 这是代码(snippet_2)

#include <iostream>
#include <chrono>
using namespace std;
using namespace std::chrono;
void functiona()
{
long long number = 0;
long long problemSize = 100000000000;
for( long long i = 0; i < problemSize; ++i )
{
for(long long j = 0; j < problemSize; j++)
{
for(long long k = 0; k < problemSize; k++)
{
for(long long l = 0; l < problemSize; l++)
{
for(long long l = 0; l < problemSize; l++)
{
number++;
number--;
}
}
}
}
}
}
int main()
{
high_resolution_clock::time_point t1 = high_resolution_clock::now();
functiona();
high_resolution_clock::time_point t2 = high_resolution_clock::now();
auto duration = duration_cast<microseconds>( t2 - t1 ).count();
cout << duration;
return 0;
}

我想问题大小足够大,snippet_2输出 0。

我错过了什么?

当人们忘记C++是什么时,就会发生这种情况。您的源代码不是计算机芯片一次执行一个的指令序列。它是对程序的描述。这是一个抽象的概念

人们喜欢谈论优化这个和发布模式那个。人们喜欢将优化器视为事后的想法,在构建过程结束时附加到与您键入的语句逐行匹配的内容。不是。这是采用抽象程序并从中创建真实内容的基本组成部分(阅读:编译过程)。优化级别最好命名为"努力级别":编译器通过越来越远离你的话来寻找一个可以在计算机芯片上很好地快速执行的真实程序,从而付出了多少努力。

您的代码,尽管以一种非常迂回的方式,描述了一个一无所获的程序。因此,您非常应该期望一个像样的编译器能够生成一个不做任何有意义工作的可执行文件。

当然,你可以用副作用和等等等等以及其他你实际上不需要测量的东西来欺骗它,但这只是错过了重点。相反,基准是实际的、有用的工作。其他任何事情都只是在浪费自己的时间!

如果程序需要延迟,请使用std::this_thread::sleep_for

它在Python中是不同的,因为它是一种解释性的脚本语言,在执行之前[通常]不会经过任何翻译。这就是为什么你正在读的书谈论的是Python,而不是C++。从Python中获取概念并尝试将它们应用于C++通常是愚蠢的。

这让我想起了我为潜在客户运行的基准测试。在竞争对手的系统上,大约需要 60 秒。在我们的系统上,它只花了几分之一秒。

区别不在于我们的CPU快得多,而在于编译器的优化器意识到它可以采取捷径,因为无需循环即可轻松优化计算。

在您的情况下,您可以递增和减少变量数,但编译器可能知道该数字不会因此而改变,因此优化了代码中的循环。

该功能正在优化。您可以通过强制编译器假定每次读取或写入变量时都有副作用来轻松解决此问题。这可以通过声明变量volatile来完成:

/* long long number = 0; --> */ volatile long long number = 0;