这是我在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(完全未优化),2​​3s,然后..零。

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

10-08 11:28