我喜欢D的某些功能,但是如果它们带有一个
运行时间的损失?

相比之下,我实现了一个简单的程序,该程序可以同时在C++和D中计算许多短 vector 的标量积。结果令人惊讶:

  • D:18.9 s [请参见下面的最终运行时间]
  • C++:3.8 s

  • C++真的快五倍还是我在D中弄错了
    程序?

    我在最近的中等Linux桌面上使用g++ -O3(gcc-snapshot 2011-02-19)和dmd -O(dmd 2.052)编译了C++。在多次运行中结果可重现,标准偏差可忽略不计。

    这是C++程序:
    #include <iostream>
    #include <random>
    #include <chrono>
    #include <string>
    
    #include <vector>
    #include <array>
    
    typedef std::chrono::duration<long, std::ratio<1, 1000>> millisecs;
    template <typename _T>
    long time_since(std::chrono::time_point<_T>& time) {
          long tm = std::chrono::duration_cast<millisecs>( std::chrono::system_clock::now() - time).count();
      time = std::chrono::system_clock::now();
      return tm;
    }
    
    const long N = 20000;
    const int size = 10;
    
    typedef int value_type;
    typedef long long result_type;
    typedef std::vector<value_type> vector_t;
    typedef typename vector_t::size_type size_type;
    
    inline value_type scalar_product(const vector_t& x, const vector_t& y) {
      value_type res = 0;
      size_type siz = x.size();
      for (size_type i = 0; i < siz; ++i)
        res += x[i] * y[i];
      return res;
    }
    
    int main() {
      auto tm_before = std::chrono::system_clock::now();
    
      // 1. allocate and fill randomly many short vectors
      vector_t* xs = new vector_t [N];
      for (int i = 0; i < N; ++i) {
        xs[i] = vector_t(size);
          }
      std::cerr << "allocation: " << time_since(tm_before) << " ms" << std::endl;
    
      std::mt19937 rnd_engine;
      std::uniform_int_distribution<value_type> runif_gen(-1000, 1000);
      for (int i = 0; i < N; ++i)
        for (int j = 0; j < size; ++j)
          xs[i][j] = runif_gen(rnd_engine);
      std::cerr << "random generation: " << time_since(tm_before) << " ms" << std::endl;
    
      // 2. compute all pairwise scalar products:
      time_since(tm_before);
      result_type avg = 0;
      for (int i = 0; i < N; ++i)
        for (int j = 0; j < N; ++j)
          avg += scalar_product(xs[i], xs[j]);
      avg = avg / N*N;
      auto time = time_since(tm_before);
      std::cout << "result: " << avg << std::endl;
      std::cout << "time: " << time << " ms" << std::endl;
    }
    

    这是D版本:
    import std.stdio;
    import std.datetime;
    import std.random;
    
    const long N = 20000;
    const int size = 10;
    
    alias int value_type;
    alias long result_type;
    alias value_type[] vector_t;
    alias uint size_type;
    
    value_type scalar_product(const ref vector_t x, const ref vector_t y) {
      value_type res = 0;
      size_type siz = x.length;
      for (size_type i = 0; i < siz; ++i)
        res += x[i] * y[i];
      return res;
    }
    
    int main() {
      auto tm_before = Clock.currTime();
    
      // 1. allocate and fill randomly many short vectors
      vector_t[] xs;
      xs.length = N;
      for (int i = 0; i < N; ++i) {
        xs[i].length = size;
      }
      writefln("allocation: %i ", (Clock.currTime() - tm_before));
      tm_before = Clock.currTime();
    
      for (int i = 0; i < N; ++i)
        for (int j = 0; j < size; ++j)
          xs[i][j] = uniform(-1000, 1000);
      writefln("random: %i ", (Clock.currTime() - tm_before));
      tm_before = Clock.currTime();
    
      // 2. compute all pairwise scalar products:
      result_type avg = cast(result_type) 0;
      for (int i = 0; i < N; ++i)
        for (int j = 0; j < N; ++j)
          avg += scalar_product(xs[i], xs[j]);
      avg = avg / N*N;
      writefln("result: %d", avg);
      auto time = Clock.currTime() - tm_before;
      writefln("scalar products: %i ", time);
    
      return 0;
    }
    

    最佳答案

    要启用所有优化并禁用所有安全检查,请使用以下DMD标志编译D程序:

    -O -inline -release -noboundscheck
    

    编辑:我已经尝试过使用g++,dmd和gdc编写程序。 dmd确实落后,但是gdc的性能非常接近g++。我使用的命令行是gdmd -O -release -inline(gdmd是gdc的包装器,它接受dmd选项)。

    查看汇编程序列表,看起来既没有dmd也没有gdc内联scalar_product,但是g++/gdc确实发出了MMX指令,因此它们可能会自动向量化循环。

    关于c++ - D与C++相比有多快?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5142366/

    10-10 10:57