一个足够大的问题大小 C++ 需要 0 个运行时间
a large enough problemSize in C++ takes 0 run time
这段用于演示算法复杂性和测量算法运行时间的代码来自一本书 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;
- std::原子加载和存储都需要吗
- 需要帮助设置在C++中使用的Potrace
- 是否需要删除包含对象的"pair"?
- Arduino:for/while/if在void setup()或void loop()之前?——错误:之前需要不合格
- C++我需要了解在哪里使用指针和双指针
- 为什么即使使用-cudart-static进行编译,库用户仍然需要链接到cuda运行时
- 这个指针和内存代码打印是什么?我不知道是打印垃圾还是如何打印我需要的值
- 在两个类中共享相同的函数调用,并在不需要时避免空实例化
- 当使用透明的std函数对象时,我们还需要写空的尖括号吗
- 我需要将多个函数组合为一个函数
- 概念中的cv限定符需要表达式参数列表
- 是否有类似std::lower_bound的函数,而不需要排序/分区输入
- 库函数需要一个 std::function<void(void)>,如何传入类函数?
- 需要从 istream 和 ostream 派生 iostream
- 我需要知道编译器如何在cpp中使用析构函数
- 为什么您需要C++头文件的包含保护
- 为什么需要复制构造函数,在哪些情况下它们非常有用
- 需要帮助将结构数组传递给函数
- 为什么output_editor Concept不需要output_e迭代器标记
- 在C++中声明一个函数时,它需要有函数本身的参数吗