这是我在 Stack 上的第一篇文章。
我通常使用 VB6 进行开发,但最近开始使用带有 g++ 编译器库的 DEV-C++ IDE 使用 C++ 编写更多代码。
我在一般程序执行速度方面遇到问题。
这个旧的 VB6 代码在 20 秒内运行。
DefLng A-Z
Private Sub Form_Load()
Dim n(10000, 10) As Long
Dim c(10000, 10) As Long
For d = 1 To 1000000
For dd = 1 To 10000
n(dd, 1) = c(dd, 2) + c(dd, 3)
Next
Next
MsgBox "Done"
End Sub
此 C++ 代码需要 57 秒...
int main(int argc, char *argv[]) {
long n[10000][10];
long c[10000][10];
for (long d=1;d<1000000;d++){
for (long dd=1;dd<10000;dd++){
n[dd][1]=c[dd][2]+c[dd][3];
}
}
system("PAUSE");
return EXIT_SUCCESS; }
我编写的大部分代码都与 AI 相关,并且大量使用数组。我试过使用 int 而不是 long,我试过不同的机器,C++ 总是运行至少慢三倍。
我是不是傻了?谁能解释我做错了什么?
干杯。
最佳答案
简答
您需要查看您的编译器优化设置。 This资源可能有帮助
要点:C++ 允许您使用许多技巧,有些是通用的,有些则取决于您的架构,如果使用得当,它将在性能方面优于 VB。
长答案
请记住,这在很大程度上取决于您的体系结构和编译器,以及编译器设置。您应该将编译器配置为进行更积极的优化。 此外,您应该编写优化的代码,同时考虑内存访问、明智地使用 CPU 缓存等。
我已经在 ubuntu 16.04 虚拟机上使用 Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz 进行了测试。使用下面的代码是我的时间,具体取决于我使用的编译器的优化级别 g++ 5.4.0
我使用优化级别 0、1、2、3、s 并获得 36s(完全未优化)、23s,然后..零。
osboxes@osboxes:~/test$ g++ a.cpp -O0 -o a0
osboxes@osboxes:~/test$ ./a0 start..finished in 36174855 微秒
osboxes@osboxes:~/test$ g++ a.cpp -O1 -o a1
osboxes@osboxes:~/test$ ./a1 start..finished in 2352767 微秒
osboxes@osboxes:~/test$ g++ a.cpp -O2 -o a2
osboxes@osboxes:~/test$ ./a2 start..finished in 0 微秒
osboxes@osboxes:~/test$ g++ a.cpp -O3 -o a3
osboxes@osboxes:~/test$ ./a3 start..finished in 0 微秒
osboxes@osboxes:~/test$ g++ a.cpp -Os -o as
osboxes@osboxes:~/test$ ./as start..finished in 0 微秒
请注意,通过使用更积极的优化级别,编译器将完全消除代码,因为 n[] 中的值未在程序中使用。 要强制编译器生成代码,请在声明 n 时使用 volatile 关键字
现在添加 volatile 后,最激进的优化(在我的机器上)将达到 ~12 秒
osboxes@osboxes:~/test$ g++ a.cpp -O3 -o a3
osboxes@osboxes:~/test$ ./a3 start..finished in 12139348 微秒
osboxes@osboxes:~/test$ g++ a.cpp -Os -o as
osboxes@osboxes:~/test$ ./as start..finished in 12493927 微秒
我用于测试的代码(基于你的例子)
#include <iostream>
#include <sys/time.h>
using namespace std;
typedef unsigned long long u64;
u64 timestamp()
{
struct timeval now;
gettimeofday(&now, NULL);
return now.tv_usec + (u64)now.tv_sec*1000000;
}
int main()
{
cout<<"start"<<endl;
u64 t0 = timestamp();
volatile long n[10000][10];
long c[10000][10];
for(long d=1;d<1000000;d++)
{
for(long dd=1;dd<10000;dd++)
{
n[dd][1]=c[dd][2]+c[dd][3];
}
}
u64 t1 = timestamp();
cout<<"..finished in "<< (t1-t0) << " micro seconds\n";
return 0;
}
多线程
我已经将您的代码转换为使用多线程,使用 2 个线程我能够将时间减少一半。
我正在使用这样一个事实,就像现在一样,结果没有被使用,所以内部的 for 不依赖于外部的,实际上你应该找到另一种方法来拆分工作,这样结果就不会覆盖一个另一个。
#include <iostream>
#include <sys/time.h>
#include <omp.h>
using namespace std;
typedef unsigned long long u64;
u64 timestamp()
{
struct timeval now;
gettimeofday(&now, NULL);
return now.tv_usec + (u64)now.tv_sec*1000000;
}
int main()
{
omp_set_num_threads(2);
#pragma omp parallel
{
}
cout<<"start"<<endl;
u64 t0 = timestamp();
volatile long n[10000][10];
long c[10000][10];
for(long d=1;d<1000000;d++)
{
#pragma omp parallel for
for(long dd=1;dd<10000;dd++)
{
n[dd][1]=c[dd][2]+c[dd][3];
}
}
u64 t1 = timestamp();
cout<<"..finished in "<< (t1-t0) << " micro seconds\n";
return 0;
}
osboxes@osboxes:~/test$ g++ a.cpp -O3 -fopenmp -o a3
osboxes@osboxes:~/test$ ./a3 start..finished in 6673741 微秒
关于C++ 运行速度比 VB6 慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53283791/