对大矢量进行定时数值运算.如何进行公平的比较
Timing numerical operations on large vectors. How to draw a fair comparison?
我正在计时一些简单的数值运算,以决定如何(即使用哪个库中的哪些工具)实现计算密集型模拟。下面的代码使用(1)MTL4 4.0.9486版本(即不使用BLAS
)、(2)std::vector
s和std::inner_product
以及(3)std::valarray
s计算矢量的两个内积的和。我选择了一个这种特定形式的玩具示例,因为它似乎是MTL4表达模板的理想基础。
为了将所有内容缩小到一个问题,下面的比较是公平的,还是(无意中)使三种方法中的任何一种处于不利地位?我有点惊讶(2)比(1)快。当然,整体模拟是否会更快是另一回事。
如果有人对更彻底的测试有任何建议,可能会揭示每种方法的优点或缺点,我很乐意尝试。
原谅代码中的宏;它们只是CCD_ 5语句和对CCD_。
提前谢谢。
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() << " msecn";
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() << " msecn";
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() << " msecn";
PRINTV(valarray_times)
PRINTME(result, aa)
return 0;
}
C++输出:
MTL4:点积的平均时间=180.33毫秒
mtl_times=177 175 174 174 175 178 176 185 184 174 175 179 175 216 188
结果:1.97392e+08
STL矢量+std::inner_product:点积的平均时间=58.6毫秒
stl_times=56 55 56 57 57 57 57 56 57 55 58 58 90
结果:1.97392e+08
valarrays:点积的平均时间64.4毫秒
valarray_times=63 64 63 64 65 63 63 63 63 64 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输出:
平均时间=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接口对整个阵列进行额外扫描。)
- 如何在 vtk Poly 数据上进行布尔运算?
- MSVC 无法根据模板参数进行数学运算,这是一个错误吗?
- 为什么对无符号字符进行算术运算会将它们提升为有符号整数
- 为什么在C++不可能递增或进行数学运算,例如在声明为数组的变量上乘法
- 用c++对链表进行异或运算
- C++中一个函数对数组进行搅乱和平方运算的问题
- 如何使用C++中的数组进行矩阵数学运算
- 对 32 位整数进行哈希处理比对 3 个 16 位整数的哈希进行按位运算慢?
- 使用 AVX 对两个 zmm(512 位)寄存器进行异或运算
- boost::spirit::x3 phrase_parse 在进入 Vector 之前进行算术运算
- C++模运算符,使用 #define 和自己的类进行浮点运算
- 在标准布局对象中进行指针运算(例如,使用偏移量)时,我们是否需要使用 std::launder?
- 在 C++11 中对字符串进行异或运算
- 如何正确地使用opengl转换的矩阵进行数学运算
- 在代码中返回3221225725以进行简单概率运算
- 为什么C++预处理器没有对枚举值进行正确的运算
- 在C++中对二维数组进行快速简单的矩阵运算
- 为什么用这种方式进行乘法运算
- C++ 为什么我不能在结构中使用或强制转换变量进行算术运算?
- 移动变量并对其进行运算