我正在安排一些简单的数值运算来决定如何(即使用哪个库中的哪些工具)实施计算密集型仿真。下面的代码使用(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/