这是我在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缓存等。
我已经在使用4.20GHzIntel®Core™i7-7700K CPU内核的ubuntu 16.04虚拟机上为您进行了测试。以下是我使用代码的时间,具体取决于我使用的g ++ 5.4.0编译器的优化级别
我正在使用优化级别0、1、2、3,s,并获得36s(完全未优化),23s,然后..零。osboxes@osboxes:~/test$ g++ a.cpp -O0 -o a0osboxes@osboxes:~/test$ ./a0 start..finished in 36174855 micro secondsosboxes@osboxes:~/test$ g++ a.cpp -O1 -o a1osboxes@osboxes:~/test$ ./a1 start..finished in 2352767 micro secondsosboxes@osboxes:~/test$ g++ a.cpp -O2 -o a2osboxes@osboxes:~/test$ ./a2 start..finished in 0 micro secondsosboxes@osboxes:~/test$ g++ a.cpp -O3 -o a3osboxes@osboxes:~/test$ ./a3 start..finished in 0 micro secondsosboxes@osboxes:~/test$ g++ a.cpp -Os -o asosboxes@osboxes:~/test$ ./as start..finished in 0 micro seconds
请注意,通过使用更具攻击性的优化级别,编译器将完全消除代码,因为程序中未使用n []中的值。
要强制编译器生成代码,请在声明n时使用volatile关键字
现在添加volatile后,您将获得约12秒钟的最积极的优化(在我的机器上)osboxes@osboxes:~/test$ g++ a.cpp -O3 -o a3osboxes@osboxes:~/test$ ./a3 start..finished in 12139348 micro secondsosboxes@osboxes:~/test$ g++ a.cpp -Os -o asosboxes@osboxes:~/test$ ./as start..finished in 12493927 micro seconds
我用于测试的代码(根据您的示例)
#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 a3osboxes@osboxes:~/test$ ./a3 start..finished in 6673741 micro seconds