我做了一个测试,通过将数组元素和单个对象的值打印到 CLI 中来查看它们之间的区别:
#include <iostream>
#include <chrono>
#include <iomanip>
int main()
{
int a[10] = {1,2,3,4,5,6,7,8,9,10};
int v1 = 1;
int v2 = 2;
int v3 = 3;
int v4 = 4;
int v5 = 5;
int v6 = 6;
int v7 = 7;
int v8 = 8;
int v9 = 9;
int v10 = 10;
std::cout << "Array output:" << std::endl << std::endl;
auto t_start1 = std::chrono::high_resolution_clock::now();
std::cout << "1. value: " << a[0] << std::endl;
std::cout << "2. value: " << a[1] << std::endl;
std::cout << "3. value: " << a[2] << std::endl;
std::cout << "4. value: " << a[3] << std::endl;
std::cout << "5. value: " << a[4] << std::endl;
std::cout << "6. value: " << a[5] << std::endl;
std::cout << "7. value: " << a[6] << std::endl;
std::cout << "8. value: " << a[7] << std::endl;
std::cout << "9. value: " << a[8] << std::endl;
std::cout << "10. value: " << a[9] << std::endl;
auto t_end1 = std::chrono::high_resolution_clock::now();
std::cout << std::endl;
std::cout << "Variable output:" << std::endl << std::endl;
auto t_start2 = std::chrono::high_resolution_clock::now();
std::cout << "1. value: " << v1 << std::endl;
std::cout << "2. value: " << v2 << std::endl;
std::cout << "3. value: " << v3 << std::endl;
std::cout << "4. value: " << v4 << std::endl;
std::cout << "5. value: " << v5 << std::endl;
std::cout << "6. value: " << v6 << std::endl;
std::cout << "7. value: " << v7 << std::endl;
std::cout << "8. value: " << v8 << std::endl;
std::cout << "9. value: " << v9 << std::endl;
std::cout << "10. value: " << v10 << std::endl;
auto t_end2 = std::chrono::high_resolution_clock::now();
std::cout<< std::endl << "Time passed with array: "
<< std::chrono::duration<double, std::milli>(t_end1-t_start1).count()
<< " msn" << std::endl;
std::cout<< std::endl << "Time passed with variables: "
<< std::chrono::duration<double, std::milli>(t_end2-t_start2).count()
<< " msn" << std::endl;
return 0;
}
在第一个实现(Windows 10,cmd.exe 下的 MingW/g++(上,数组元素内的值打印平均比使用单个标量对象慢 3毫秒:
Windows 表,g++/MingW:
Array Elements: Single Objects:
1. Run 13.9609 ms 9.529 ms
2. Run 11.9031 ms 8.0936 ms
3. Run 13.3706 ms 9.5264 ms
4. Run 12.5302 ms 8.4723 ms
5. Run 14.4679 ms 9.9688 ms
6. Run 12.3989 ms 8.4326 ms
7. Run 12.8719 ms 10.1851 ms
8. Run 10.9138 ms 7.4481 ms
9. Run 12.8971 ms 9.4094 ms
10. Run 11.9045 ms 7.9391 ms
11. Run 9.9192 ms 8.4047 ms
12. Run 13.4106 ms 10.0296 ms
在第二个实现(Linux Ubuntu 下的 g++(上,数组元素内的值打印平均比使用单个标量对象慢 3微秒:
Linux Ubuntu, g++ 的表:
Array Elements: Single Objects:
1. Run 0.013 ms 0.008 ms
2. Run 0.012 ms 0.007 ms
3. Run 0.013 ms 0.008 ms
4. Run 0.014 ms 0.009 ms
5. Run 0.012 ms 0.008 ms
6. Run 0.013 ms 0.008 ms
7. Run 0.013 ms 0.009 ms
8. Run 0.014 ms 0.009 ms
9. Run 0.012 ms 0.008 ms
10. Run 0.013 ms 0.009 ms
11. Run 0.012 ms 0.009 ms
12. Run 0.012 ms 0.008 ms
我的问题:
- 为什么在 *C++ 中打印数组元素中的值平均比打印单个对象中的值慢?
*信息:我不知道数组元素的打印是否总体上平均较慢,与特定语言无关。
如果您查看生成的程序集,您会注意到编译器将数组元素和标量的负载替换为常量,因为它们的值在编译时是已知的。
您可以测量格式化和输出数组元素所需的时间,以及刷新每个元素上的输出流(使用std::endl
(,这涉及系统调用。
从数组加载元素比这短得多。从一级缓存加载 CPU 寄存器需要 4 个 CPU 周期(在 5GHz CPU 上不到 1 纳秒(,从 i9-i9900KS 上的内存(最后一级缓存未命中(加载 ~215 个 CPU 周期,在锐龙上需要 ~280 个 CPU 周期。
从数组或(标量(变量加载元素之间应该没有可测量的区别。从数组加载元素可能涉及生成的程序集中的一些索引算术,但这可能很难测量。
当我围绕您的时序进行循环以使 CPU 将其频率提高到最大值时,页面错误页和预热 CPU 缓存;并将std::endl
替换为'n'
我得到以下时序:
Time passed with array: 0.029154 ms
Time passed with variables: 0.029286 ms
Time passed with array: 0.027148 ms
Time passed with variables: 0.027587 ms
这是为了表明访问数组元素和标量变量之间没有可测量的时间差(但它仍在测量std::cout
次(。
在你的测试中,给cout写东西比仅仅在内存中访问这些东西需要更多的时间。
更糟糕的是,它甚至可能不会从数组或变量中读取值,因为该值在编译时已经知道。在这两种情况下,它可能只使用常量。
为了证明这一切,只需尝试与硬编码常量的输出时间进行比较。并尝试将其与计算和输出这些数字之和所需的时间进行比较。
不过,我们无法确定首次输出较慢的原因。这仅取决于操作系统如何处理这些输出流。