我正在安排一些简单的数值运算来决定如何(即使用哪个库中的哪些工具)实施计算密集型仿真。下面的代码使用(1)MTL4 4.0.9486版本(即,不带BLAS),(2)std::vector s和std::inner_product以及(3) s。我选择了这种特定形式的玩具示例,因为它似乎是MTL4表达式模板的理想基础。

为了将所有问题缩小为一个问题,以下比较是否公平?或者(无意地)使这三种方法中的任何一种处于不利地位?我对(2)比(1)更快感到惊讶。当然,整体模拟是否会更快是一个不同的故事。

如果有人对更彻底的测试有任何建议,可能会揭示每种方法的优缺点,我很想尝试一下。

赦免代码中的宏;它们只是std::valarray语句和对std::cout<<实用程序的调用。

提前致谢。

C ++代码:

#include <iostream>
#include <valarray>
#include <vector>
#include <algorithm>
#include <boost/numeric/mtl/mtl.hpp>

int main(int argc, const char * argv[])
{
    /* DOT PRODUCTS */
    constexpr int trials{15};
    std::vector<double> mtl_times(trials, 0.0), stl_times(trials, 0.0), valarray_times(trials, 0.0);

    constexpr size_t sz{10000000};
    double val = M_PI;
    mtl::dense_vector<double> m(sz, val), n(sz, val), p(sz, val), q(sz, val);
    std::vector<double> y(sz, val), z(sz, val), v(sz, val), w(sz, val);
    std::valarray<double> b(val, sz), c(val, sz), d(val, sz), e(val, sz);

    double x{0.0}, k{0.0}, aa{0.0};
    auto t0 = NOW
    auto t1 = t0;

    for (int i = 0; i < trials; ++i) {

        // MTL4 vectors
        t0 = NOW // call now() from <chrono>
        k = dot(m, n) + dot(p, q);
        t1 = NOW
        mtl_times[i] = DURATIONm // duration cast of (t1-t0).count()

        // STL vectors
        t0 = NOW
        x = std::inner_product(y.begin(), y.end(), z.begin(), 0.0) + std::inner_product(v.begin(), v.end(), w.begin(), 0.0);
        t1 = NOW
        stl_times[i] = DURATIONm

        // valarrays
        t0 = NOW
        aa = (b*c + d*e).sum();
        t1 = NOW
        valarray_times[i] = DURATIONm

    }

    std::cout << "MTL4: average time for dot product = " << std::accumulate(mtl_times.begin(), mtl_times.end(), 0.0)/mtl_times.size() << " msec\n";
    PRINTV(mtl_times)
    PRINTME(result, k)
    std::cout << '\n';

    std::cout << "STL vectors + std::inner_product: average time for dot product = " << std::accumulate(stl_times.begin(), stl_times.end(), 0.0)/stl_times.size() << " msec\n";
    PRINTV(stl_times)
    PRINTME(result, x)
    std::cout << '\n';

    std::cout << "valarrays: average time for dot product = " << std::accumulate(valarray_times.begin(), valarray_times.end(), 0.0)/valarray_times.size() << " msec\n";
    PRINTV(valarray_times)
    PRINTME(result, aa)

    return 0;
}


C ++输出:


  MTL4:点积的平均时间= 180.333毫秒
  
  mtl_times =
  177175174174175175178176185184174175175175216216188
  
  结果:1.97392e + 08
  
  STL向量+ std :: inner_product:点积的平均时间= 58.6毫秒
  
  stl_times = 56 55 56 57 57 56 57 56 57 55 55 58 56 58 90
  
  结果:1.97392e + 08
  
  valarrays:点积的平均时间= 64.4毫秒
  
  valarray_times = 63 64 63 64 65 63 63 63 63 63 63 63 64 64 77
  
  结果:1.97392e + 08


根据记录,MatLab表现出色:

MatLab代码:

trials = 15;
times_ms = zeros(1, trials);

sz = 1e7;
val = pi;
x(sz) = val;
x(1:end-1) = val;
y(sz) = val;
y(1:end-1) = val;
v(sz) = val;
v(1:end-1) = val;
w(sz) = val;
w(1:end-1) = val;

z = 0;

for i = 1:trials

    tic
    z = x*y' + v*w';
    times_ms(i) = toc*1e3;

end

avg_time = sum(times_ms)/length(times_ms)
times_ms
z


MatLab输出:


  avg_time = 56.0687毫秒
  
  times_ms = 56.8919 57.2052 55.3179 55.5126 55.7660 55.3982 55.1044 55.4809 57.7229 56.1902 57.3888 56.5263 55.2830 55.4926 55.7501
  
  z = 1.9739e + 08


这并不奇怪,因为优化了内置操作,但是在仿真中使用MatLab还存在其他障碍。

最佳答案

一遍又一遍地计算点积可能会限制内存。如果要大致了解可以预期的速度差异,最好比较矩阵乘法之类的方法。点产品也非常简单,您可以检查汇编代码以查看发生了什么。我鼓励你这样做。

您的比较对valarrays不公平;您创建两个数组,然后将它们加在一起,然后求和。计算两个和并将它们相加可能更好。 (我不知道如何避免使用valarray接口对整个数组进行额外的扫描。)

关于c++ - 对大 vector 进行数值运算计时。如何进行公平的比较?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22950119/

10-13 08:18