爱吱声

标题: C++ 比 Octave 慢好多,怎么破? [打印本页]

作者: 雷达    时间: 2022-9-23 06:27
标题: C++ 比 Octave 慢好多,怎么破?
本帖最后由 雷达 于 2022-9-23 06:29 编辑 ; V# A1 R$ h' n( _# a3 ]" U
% ^7 |4 Y& }- N+ L
做一个数字信号处理的小算法,需要算互相关。
1 D; m5 l" s$ K3 r先用 Octave (兼容matlab 那个东东) 做了一下,感觉慢,走通后就用C++ 重写,结果比 Octave 还慢,目测能慢10倍,很不科学啊。% F( W& \' z8 I5 |; t6 I' i
  j1 Y5 o4 D$ |* X6 L7 {+ \, [
Octave的互相关有现成函数 xcorr,  C++ 需要自己写。互相关是一个一维矢量和一个二维数组里的矢量依次做。矢量里是复数数据,没有用 STL,自己做了个  Re/Im 的struct,其实就是两个四字节 float 。
1 J! @% O5 C$ s5 O( m互相关的最基本运算是两个复数的乘法,就是四次 float 乘法再相加,所以本质上影响速度的应该就是 float 乘法和加法。
& q  y$ e  x2 ^4 Z
' ~. m5 v( B* t. Z. }9 NC++ 用的是VS 社区版,估计编译器不给力,但也不至于差这么多啊。4 C5 K$ E/ G0 }$ u+ x3 U+ l
8 l6 g3 {% Q! l8 G7 R; I
高手们给分析分析,  多谢了。4 V6 z6 Y( ^( k2 W1 t% d1 }

作者: 雷声    时间: 2022-9-23 07:02
互相关这种是最适合矢量化的,Octave应该是用SIMD 或者CUDA写了核心的计算部分。所以比没有优化的快很多。我差不多20年前做过类似的二维相关处理,优化过的比老师自己写的快了三四十倍,实验室的小崽子们怨声载道。因为本来等处理完一次数据需要差不多六七个小时,正好打游戏。优化完了之后不到二十分钟就好了。啥也干不了。- y. o3 t% m, @
你想省事的话用Intel的IPP库,里面有现成的高度优化的互相关函数。或者用CUDA自己写一个。
' g3 u- B- ~7 C8 I你做信号处理很熟的话,这个还可以用FFT来做。应该会更快一些。九十年代很多人这么处理,主要是那时候CPU实在太慢。现在基本用不着了。而且FFT前后处理比较麻烦,加窗什么的。
作者: 雷达    时间: 2022-9-23 08:13
本帖最后由 雷达 于 2022-9-23 08:15 编辑 9 v9 T, A8 w( X5 i5 O5 R0 Y  h
雷声 发表于 2022-9-23 07:02- Y! z8 d7 C0 g' l* u
互相关这种是最适合矢量化的,Octave应该是用SIMD 或者CUDA写了核心的计算部分。所以比没有优化的快很多。 ...
1 p6 T- j6 {6 ~& I9 h7 O7 _
5 C" s( E; e% u1 Y' ~
嗯, 我就是觉得 FFT 反而麻烦,互相关代码本身倒真没有几行。那看来就用 octave 就好了,没必要再用C++重写了。
/ Q& |' [+ w' Q) r- I2 g) J- y另外,我现在就是用指针数组,如果用 STL 的Vector 会不会更快一些?
作者: 可梦之    时间: 2022-9-23 09:18
Octave/Matlab内部对数值计算做了很多并行和优化。内核甚至是用Fortran写的。你用C++重写,没有做并行优化,真未必比他们的性能好。
作者: 阿忙    时间: 2022-9-23 09:55
Matlab不是浪得虚名的,要打败它还是要下点功夫才行
作者: 雷达    时间: 2022-9-23 11:00
本帖最后由 雷达 于 2022-9-23 11:10 编辑 / ?2 O5 c6 H, C6 h8 a
  [& U: Q9 ?; I8 s! R  v- u
研究了一下,似乎可以用预处理指令对浮点运算做一些优化。这个问题比我最初想象的要复杂得多
作者: 马鹿    时间: 2022-9-23 11:18
汇编快!
作者: 数值分析    时间: 2022-9-23 11:34
本帖最后由 数值分析 于 2022-9-23 11:48 编辑
2 H- B1 @) p! f) m9 _! `
; M# J: H% w$ H! TC++ code 用的是普通乘法?换成sse/avx向量乘法试试?
$ q; B( D) Q! I/ ~( ~并且是单线程的?加个openmp并行试试
3 n2 Z5 N  t- x/ y或者调用mkl 库的互相关函数试试  i4 \5 ?( B; {- Q

作者: mark    时间: 2022-9-23 11:43
马鹿 发表于 2022-9-23 11:18; x  ~" o- u3 d9 Y/ u
汇编快!
$ _- [: d; Y- e1 s( n" v
这种问题的优化, 在语言层面没太大意义, c++和汇编没什么本质区别.' M: s$ O6 P5 v0 n" S0 M

4 z0 h! y7 q; n( A( ~最好还是用高性能的计算库, 比如intel的ipp,或者看看gpu方面有没有类似的库.
作者: 走两步    时间: 2022-9-23 12:59
涉及矩阵的用blas
作者: 雨楼    时间: 2022-9-23 14:05
实际使用中要考虑综合成本/时间。比如用octave /Python 解决起来简单。自己另起炉灶麻烦些。
作者: 雷声    时间: 2022-9-23 15:48
雷达 发表于 2022-9-23 08:13# O) y% `3 ]4 E4 {. D
嗯, 我就是觉得 FFT 反而麻烦,互相关代码本身倒真没有几行。那看来就用 octave 就好了,没必要再用C++ ...

" ~8 ?$ z. `/ TSTL对性能优化没什么帮助,只是写起来比较安全而已。
- j% z( h4 y+ T) v2 B- s* [下面数值分析回答的是对的,要么用avx自己写,要么就凑合用octave得了。. t2 p8 y4 _2 r; w2 b
买个Ipp库虽然不贵,但是还是要几百刀的吧?# H+ _& p! [, O8 V/ Q* D$ i

作者: 四处张望    时间: 2022-9-23 16:05
矩阵最简单用eigen,然后enable  avx2以上
作者: 马鹿    时间: 2022-9-23 20:24
mark 发表于 2022-9-22 22:43/ x5 i* I/ U( K6 V. S0 h' `" o
这种问题的优化, 在语言层面没太大意义, c++和汇编没什么本质区别.9 j& `0 z, N- k3 E

$ y5 l0 l" m* W& q. U9 B2 N最好还是用高性能的计算库, 比如inte ...

1 R# v0 [" W! D. Z9 z, g8 i我不是it的,说汇编是起哄呢
作者: 沉宝    时间: 2022-9-23 20:53
雷声 发表于 2022-9-23 15:48" {1 O+ z5 n8 h* _: {
STL对性能优化没什么帮助,只是写起来比较安全而已。/ A4 x# J, n7 r; ]# x3 t8 a1 i
下面数值分析回答的是对的,要么用avx自己写,要么 ...

! o3 r6 l# s6 \! |$ t1 T你觉得在用AVX自己写与用GPU加速的Octave之间,谁有可能性能上超出?(基于中等价位的硬件水平)
作者: 数值分析    时间: 2022-9-23 21:37
本帖最后由 数值分析 于 2022-9-23 23:50 编辑 : ^9 @6 r7 `) B9 w* t
沉宝 发表于 2022-9-23 20:53
" Z9 X7 I) p7 |% x1 M' F你觉得在用AVX自己写与用GPU加速的Octave之间,谁有可能性能上超出?(基于中等价位的硬件水平) ...

5 _6 ?# s4 M% j- S1 h& e1 b. S1 {5 H9 {) n- w
必然是GPU啊,10来个核心对上千个计算单元。。。8 H8 ?& f8 J( O- D) j- ^9 d: V$ N
) ^$ z+ b/ J$ N) ?5 B+ H9 X9 o
有道是 双拳难敌四手 一虎不如群狼
作者: ltpub    时间: 2022-9-26 18:34
先用性能探查器看下热点在哪里,用前面坛友们的方法针对性优化下,满足了应用需求就收手(心中牢记那句箴言:又不是不能用!)% |6 T9 q. r* k% o9 N6 D: Y2 [7 X

3 N% o: C' K& H8 A) Y不知道vs的社区版带不带性能探查器,不行的话用pro/ent试用几天应该是不违规的,实在不行把C++编译到Linux下,那perf工具可就多了去了
作者: 机器猫    时间: 2022-9-26 23:30
mark 发表于 2022-9-23 11:43
6 H! V, T% z0 p- H( m7 j0 k这种问题的优化, 在语言层面没太大意义, c++和汇编没什么本质区别.% i% K5 d9 J0 v/ N+ \* ?  X7 h

5 F9 O5 r  D4 R* f1 c) R1 e最好还是用高性能的计算库, 比如inte ...
3 m" g( W+ s- x7 Y
区别还是很大的。编译器的优化还到不了那种程度。
6 s* T/ U$ P  b. j! Y7 H  w* }你说的那些“高性能的计算库”很多估计都是专门的人用汇编手工优化出来的。那个得对要优化的系统非常熟悉的人来干,打个比方那条指令用在哪个地方会导致cache需要加载,这些都必须考虑到
$ h  f4 E8 F: S; U- _' c; x/ h" ^* S8 H) [3 v" B7 L$ e
当然对于调用这些库的代码来说,一般C和汇编区别不大
作者: 沉宝    时间: 2022-10-2 01:38
现在进展怎么样了?2 Y9 U6 m8 h: K; D2 c

% m" ?9 L8 }: b想了解一下你问题的规模:
" |/ N; z1 m1 ]: f9 U" Q, Y1) 你说互相关是一个一维矢量和一个二维数组里的矢量依次做,那么这个二维数组有什么特殊意义吗?需要对所有维度按列操作并返回一个矩阵,还是就是简单的一对一算过去?换一句话,本质上要的是一个1-维互相关算法,还是N-维互相关算法。) }' l' b6 P% @# P/ R( ^( b
2) 矢量和一个二维数组的长度大概是多少?9 X$ z; @8 ~6 }. m/ P
3) Octave 大约跑了多长时间,你心里期望的速度大约是多少?
作者: 雷达    时间: 2022-10-2 03:04
本帖最后由 雷达 于 2022-10-2 03:06 编辑 8 X6 z2 n9 H9 O" l9 f% j0 r0 q
沉宝 发表于 2022-10-2 01:38
5 V% D. }/ s. G" _) A6 N5 b. `+ L现在进展怎么样了?/ W/ d" B/ d% W& q2 K
( h, ^4 @5 P+ }0 n6 n6 Y. E, h% T
想了解一下你问题的规模:
# i+ F$ O, k0 a6 M' \

3 ?# F6 c1 ~8 \多谢关注。
9 M7 `  O+ `7 V6 p规模还比较大,一个至少3万*3万的二维浮点复数矩阵,用一个4000点复数矢量对矩阵的每一个3万点矢量做互相关,重复3万次这种互相关。 ! _7 @% R. x/ W* z; v
我已经试验成功了 AVX 算浮点内积和 VS 优化, 再加上多核并行,我希望能至少和 octave 打平。但现在手头有其他事,还没有时间改正式代码。
作者: 沉宝    时间: 2022-10-3 01:16
雷达 发表于 2022-10-2 03:04
" N9 M0 `+ K( h, J0 s) Q多谢关注。
, h+ m/ s7 h5 z, c' C) A规模还比较大,一个至少3万*3万的二维浮点复数矩阵,用一个4000点复数矢量对矩阵的每一个3万 ...

& U# Y) V/ v8 U: g- A9 b( u* f! l你在 Octave 跑出来的速度是多少?没有具体数据的话能不能说一下数量级上大致在哪里?
5 M5 K3 S; C! O& R/ e" _& J3 }
3 O2 L) [& X1 E8 X/ J另外,你在 Octave 上的测试是按实际数据量跑的吗?我大概估计了一下,如果我没有算错,你那个二维浮点复数矩阵的数据量大约240TB(1 billion elements, each element has 30000x8 bytes)。这么大的数据量不可能全都放进内存中准备好,(事实上,它们已经不是一块硬盘可以装得下的了,放在磁盘阵列上吗?)有可能计算机的I/O吞吐性能也成为影响真正计算速度的一个重要因素。
作者: 雷达    时间: 2022-10-3 09:13
本帖最后由 雷达 于 2022-10-3 09:16 编辑
7 x+ x7 D" p+ Z7 p
沉宝 发表于 2022-10-3 01:16' p. g9 e! M; G, R& x" W
你在 Octave 跑出来的速度是多少?没有具体数据的话能不能说一下数量级上大致在哪里?
6 X/ M( N; D9 `6 H0 r3 p# k( g7 c% M' H  @
另外,你在 Octav ...
- }( j  `" m3 ^' X: i
- @. w+ H/ E( \) _% L6 Z: R, X
应该没有那么大。6 F$ z# [6 v) N9 F5 N
我算的:
  [. u* x2 A' j" Q/ ?3万*3万的二维浮点复数矩阵, 30k*30k = 900M个点, 复数 *2, 浮点数 *4,总共 7.2G。1 o! t2 ]0 q1 K! k; Z3 w# z
做算法的时候,一行一行从文件读取,有个16G内存应该足够了




欢迎光临 爱吱声 (http://aswetalk.net/bbs/) Powered by Discuz! X3.2