设为首页收藏本站

爱吱声

 找回密码
 注册
搜索
查看: 5503|回复: 25
打印 上一主题 下一主题

[信息技术] C++ 提速的新发现

[复制链接]
  • TA的每日心情
    擦汗
    2024-12-25 23:22
  • 签到天数: 1182 天

    [LV.10]大乘

    跳转到指定楼层
    楼主
     楼主| 发表于 2022-9-24 22:54:26 | 显示全部楼层 |只看大图 回帖奖励 |倒序浏览 |阅读模式
    C++ 比 Octave 慢好多,怎么破?9 G8 |/ |7 G# g8 y: G* D& t: h& |) p
    - t8 \- }1 X* R1 W+ [6 I( x0 S# V/ p
    自相关两层循环,内层循环涉及浮点数计算,试验了一下把内层循环内部全都 comment out 只留个壳子,  但空的内层循环本身就把速度拉下来了,看来问题并不在浮点计算。8 G; U0 W2 [8 p3 Q. B$ G2 V3 z% j* j

    8 _  c4 A8 b& L2 Y. o速度优化问题真的很有意思啊。
    ! P0 C! }2 T2 G) X! w
    4 P2 Y, a$ J1 c* U- k! l' X欢迎大家继续讨论

    评分

    参与人数 2爱元 +8 收起 理由
    helloworld + 4
    住在乡下 + 4 涨姿势

    查看全部评分

  • TA的每日心情
    擦汗
    2024-12-25 23:22
  • 签到天数: 1182 天

    [LV.10]大乘

    沙发
     楼主| 发表于 2022-9-24 23:54:10 | 显示全部楼层
    本帖最后由 雷达 于 2022-9-24 23:57 编辑 % q2 B8 G6 C& |6 J- q$ P" D
    数值分析 发表于 2022-9-24 23:04
    4 X/ |/ x/ ]  H: \拉下来?拉多少?
    * u" X+ v/ F" H2 T# _  I把代码贴上来看看?
      ~  G9 f& {/ T0 T" A

      T2 ~% g5 M9 ~  U5 ~  Evoid xcorr(comp* outcomp, comp* A, int lenA, comp* B, int lenB)
    / O3 k9 M& Q5 U$ B+ Q3 [4 N- b{
    ; q5 ?/ v* Q7 G2 L2 |: N" [  _        comp temp, xtimesy;
    " y- x6 ~* m& z, W2 P        xtimesy.re = 0;
    * R: Z( `" _" j7 d" t- [1 S        xtimesy.im = 0;6 g; O+ X4 Y# Z
            int j0 = lenB - 1;
    ) i, r. Q1 k; H        int    i, j, i1, reali;
    5 Q% k* N; b6 g& t2 }        if (lenA % 2 == 1)1 \4 @! h2 d/ ^/ ^
                    reali = lenA + 1;# [; R' `. P. Q2 f1 a. _! y$ ~
            else/ M- X$ r0 p2 f0 j+ Z% ?7 G
                    reali = lenA;' @2 ~$ Z8 Y2 F' G8 o1 T6 d
            reali /= 2;
    8 n) z  y1 o/ E/ A2 q+ e" g6 I4 y$ @8 G) L
            int nconv = reali + lenB;
    ; E9 d) Z- {( m7 V3 A9 m        //#pragma omp parallel for- R7 F1 g5 \  A& ^3 ~6 q) h! k
            for (i = reali; i < nconv; i++)- Y" E3 Z( p% `: v
            {
    ; @/ D! q6 k9 ]* B. S/ R- ]                temp.re = 0;
    ' Z9 q' ^, \" j: U& a                temp.im = 0;
    + i( w% ]1 z  y# U8 C/ t                i1 = i;
    + A" p. E% k1 M6 ~                for (j = j0; j >= 0; j--)
    0 y2 k* E/ c1 a( i- V! ~- @                {* s' u- j! [: Y, ]% ?. Z9 S! e
                            /* floating date operation */! w! o  P  j) A- t  x3 w( w, }
                    }
    / X" ?7 `, s$ k8 h8 H  T
            }
    4 G/ S" i% ]  R$ _" l}
    $ R' u8 n2 |3 \# g' _" e$ z2 F' {* K, w
    xcorr函数代码如上,comp是复数struct, 做过长度为11、19两个矢量的测试,和octave结果完全一样
    ) K3 G  R6 X9 `& k& R
    ( Y( J  u  u6 x红色部分是内循环,现在其内部操作都comment out 了, j0大概是 6000。
    - f, }* b. O( T- w+ M& C0 j现在call xcorr 100次,耗时78s.
    / a" e+ q6 _4 o1 ?/ M9 t7 \8 t- n6 o2 r' q6 C( d
    如果把红色部分内循环本身完全comment out, call xcorr 1000次,耗时 <1s. 0 u& d+ R7 @8 o9 C" N/ T, L
    8 @" e0 f0 U" p
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    擦汗
    2024-12-25 23:22
  • 签到天数: 1182 天

    [LV.10]大乘

    板凳
     楼主| 发表于 2022-9-25 00:17:17 | 显示全部楼层
    风雨无阻 发表于 2022-9-24 23:33* t% b7 m  ^6 k% ^, z9 j
    Maybe Debug mode?

    8 n0 p5 v$ f' @/ H2 E5 w! P4 e4 U# q, j' r8 @- E% X  g
    不应该,看我上面的回复。
    + V/ `8 b. k1 O  u( `5 w3 d- H
    : d  N* A' ?$ p! {, G我更怀疑是 VS 社区版的问题
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    擦汗
    2024-12-25 23:22
  • 签到天数: 1182 天

    [LV.10]大乘

    地板
     楼主| 发表于 2022-9-25 00:46:56 | 显示全部楼层
    本帖最后由 雷达 于 2022-9-25 01:09 编辑 2 m" `( e5 z& N) X9 B& b
    数值分析 发表于 2022-9-25 00:201 n, t8 e0 W, Y2 k& p. R
    这个不是这么比的吧。。。. ]9 m# o6 o5 [  f, x) X. w4 M

    8 h  P: r: w' }您这个函数,不带内循环的话,汇编完总共操作也没几个(不到100个)。

    3 C5 |: C) T& A! Y* _0 J5 d: R" P0 _
    6 {2 d, ^; L' b$ F- p1 L+ Y有道理。
      f* Y8 F* Z, q8 M所以存在内循环速度就上不去,把内循环取消,改成两个向量直接点乘再求和应该就会好得多,记得 numeric 库里有算向量内积的,我回头试试。
    6 z% K2 f# c: W# @( N' V" `& d. M8 g: v
    我先尝试尽量用标准库,一个小程序,不想搞得太复杂。多谢了
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    擦汗
    2024-12-25 23:22
  • 签到天数: 1182 天

    [LV.10]大乘

    5#
     楼主| 发表于 2022-9-25 04:47:43 | 显示全部楼层
    本帖最后由 雷达 于 2022-9-25 04:49 编辑
    0 }2 p; J' O3 @
    沉宝 发表于 2022-9-25 01:27
    2 p; X# v" V+ ]$ M7 s% F你两个试验之间就差了一个空循环, call 1000次按理不会有秒级差异,可能还是编译器优化的问题。举个例子 ...
    % t- B$ h8 ]( _4 S" D. v
    / \6 A$ |2 C6 @7 B
    又写了个小实验,没有调用子函数,双层循环,外层6千次,内循环30万次空转,有或没有空转内循环,时间差一倍,我上面这个差的太多了。
    5 _3 p0 b6 i4 S$ T' n, h: k( o4 s' w
    我已经完全懵了。
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    擦汗
    2024-12-25 23:22
  • 签到天数: 1182 天

    [LV.10]大乘

    6#
     楼主| 发表于 2022-9-26 01:30:03 | 显示全部楼层
    本帖最后由 雷达 于 2022-9-27 01:17 编辑 ) E+ M. L/ ?9 f
    数值分析 发表于 2022-9-25 14:58% t/ p( I5 H& a! S, G" j
    能不能把这个也贴上来,看看和上一个有什么不同?
    " O! ?4 ~, Z% }/ [( p: Y; R; w% l6 T$ J
    理了理思路,重新做了一个测试。, A  Q, I9 c6 M7 p
    做了两个 vector 和 两个 float *, 都长 100000
    , Y! o) f; J1 e0 u9 H; B- g3 W外循环 6000,里面先做随机数生成,模拟真实环境,避免数据的 cache.- E2 o2 U1 @8 \5 L% M. q8 R

    . s+ P; Y: E* J内循环试了4种方法,$ |/ K( X. s7 H( U) ~. {
    1. 直接调用 vector inner_product 247s / L5 [$ O) A- K# |! l4 G
    2. vector 循环点乘累加 237s
    8 r( W$ J% V% \' {) n$ q  w3. float * 循环点乘累加 204s
    1 a- w4 x1 d3 A( _4 V* P/ U4. 空循环 100000 次 202s: i$ j2 F( {/ n" _0 }) j
    4 w% l" S. K4 @, x# e3 c6 i
    不做内循环 200s
    ( H" _  x+ Q1 r% \! k- \& ?+ J. z- N8 m& D" Q# N% m
    你昨天说的对,内循环本身占比是很小的,大头在其他处理。
    ' V  L8 w( E9 E4 q. m4 R* R8 p3 V另外可以看到, float * 循环点乘累加 并不差,比用vector 还更快。; K6 C$ W* y% x& {, I; p) h
    : y* X/ _( U- @
    至于我那个原始程序,还有一些疑问,见5楼,其他都不变仅仅是有无空的内循环就有很大不同,这是不对的,也许有一些其他缺陷我没有看到。(也许可以改成 while 试试); `. c3 W  t& G; i/ ~" |
    2 S3 J0 C+ u3 F4 y( A0 l: h
    (为什么下面我贴的  b1 加 方括号里的 i , 显示出来却是 b1 ?方括号 i 消失了。 LOL . 改成  jj 好了,原来 方括号里的 i 是斜体标志  LOL)
    - y+ h" x& j9 C6 J9 s$ C8 `
    : n# [3 U  E. x8 p8 G  g5 z0 g
            std::vector < float > vec1(N);# ^# d) @+ P& g9 t1 k% [0 ?0 q
            std::vector < float > vec2(N);/ p3 y- C( ^. a0 c  e
            float* b1 = new float[N];
    9 c+ n7 C% u" a" e: T* E* {        float* b2 = new float[N];
    $ p3 e4 `6 Y4 a: A7 |$ N
    4 F9 M  n. u, Y7 m, q) b, ?- g( Q        for (int j = 0; j < 6000; j++)$ Q) C1 Q6 \9 Z
            {" e1 y3 R" x+ a
                    std::generate(vec1.begin(), vec1.end(), []() {& I6 t/ |3 A1 j3 d& D8 ?: b
                            return static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / 23.23));;- X) k" u& t3 y
                            });# N1 o7 @1 F+ O0 T
    % t5 p9 L4 C/ E( G. r$ x2 I' l
                    std::generate(vec2.begin(), vec2.end(), []() {4 Q9 s9 A2 I# |
                            return static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / 24.31));;
    7 ~+ S: {8 @9 T                        });$ ~7 f& Y; I8 E4 x" E
    & Y( _3 B" _6 F; J$ |
                    for (size_t jj = 0; jj < vec1.size(); jj++)
    $ M) t+ h, J' D' G$ a# P' ^& Y                {" d7 m; r3 S0 y% g1 n
                            b1[jj] = vec1[jj];
    ) a  y: Y5 U7 `0 u                }
    # ^' a# b5 H3 J
    + Z' n* K) M5 c; O& k                for (size_t jj = 0; jj < vec2.size(); jj++)1 I# z2 e" v1 i
                    {
    + A& e$ ~6 {" r" z                        b2[jj] = vec2[jj];
    ! X4 b' r) _4 c+ v2 Q5 ~2 J                }' M2 x# W& E+ G$ e6 ~+ f5 [, x

      d9 c) _% Y. A6 A5 C/ J                //Method - 1  N=100000 247s  
    ) C& b2 {: D- u1 n! n/ k                //fresult = inner_product(vec1.begin(), vec1.end(), vec2.begin(), 0);: q+ e* s; M# N  M1 }4 U5 r# i+ g
                                    
    2 z2 B5 J8 X. z! D2 g                //Method - 2  N=100000  237s1 {$ ^/ [9 {2 r) n4 L
                    /*
    ) A# ^7 r# b  [! L+ |                for (int jj = 0; jj < N ; jj++)
    : k% z1 ^: S' U. g' o  [                {
    . t6 O8 H% F) B- T! s                        fresult += vec1[jj] * vec2[jj];
    / q; m) V; \. a+ h2 u  i' h                }
    " D2 G+ N+ f# W2 C$ h% S; n* x* p                */: @- K$ ]5 g" Y9 N' T2 m
                                    
    ) p$ @4 v2 ?5 o9 {                //Method - 3  N=100000 204s+ H; ?3 b& c. l* G6 L
                    /*
    $ E& w7 ~) n) J* q                for (int jj = 0; jj < N; jj++)! d/ x* l) n0 N4 |- V! A
                    {
    2 p- J' c9 D0 M4 q2 ~                        fresult += b1[jj] * b2[jj];
    5 i& d6 s4 I- d# K' b                }) z9 H3 R% P" U0 s  k. t' ?4 K
                    */& C1 |, d" [7 D9 S; f
    ) G+ e) C: W8 Z, U7 t
                    //Method - 4   202s8 E- Q  F* b" h" S
                    /*. h; U5 ?1 z& L% Q
                    for (int jj = 0; jj < N; jj++)# J8 M3 M, p- o7 R9 H
                    {+ g8 E& a4 Q4 h# x
                            / H) @7 E4 y, n- h" W# e; f, _. R
                    }
    9 y# ?: G- O6 E1 c                */% M& ]/ i; K- z) e1 T6 h" I
                    //comment out all methods, N=100000  202s                ) O0 w4 r1 H" v$ A  V
            }
    # m8 K7 {, b; H1 u  c& q, h6 q$ ]0 [( |  V. }
            delete []b1;
    : t" Z: O3 B& F8 r, f9 j        delete []b2;
    6 J' s- \* \3 z7 @) _& ~
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    擦汗
    2024-12-25 23:22
  • 签到天数: 1182 天

    [LV.10]大乘

    7#
     楼主| 发表于 2022-9-27 01:16:03 | 显示全部楼层
    机器猫 发表于 2022-9-27 00:151 w3 `5 {7 t# f4 h0 g/ O
    瞎猜一下啊。把第一个的那个j定义成register变量会不会有不同?  {" D* b4 \7 g- @0 A5 H9 E6 t% h8 a

    / ~; O, _+ [6 T  r) L! [/ \你第二个试验里面的j在循环里面又重新定义 ...

    # B! o! A' a8 p3 s& M8 k内循环里面的 j 实际是 i, 为了规避爱坛显示的冲突帖子里临时改成了j, 现在是 jj 了。好累 、LOL1 [6 f- t. O2 Q7 H/ O- R5 ~
    , e7 t: i9 \  q0 K0 V5 N! N: o
    不和它较劲了,瞎耽误工夫,我已经转到 ubuntu, 也准备顺便试试 avx2 向量化。
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    擦汗
    2024-12-25 23:22
  • 签到天数: 1182 天

    [LV.10]大乘

    8#
     楼主| 发表于 2022-9-27 22:41:56 | 显示全部楼层
    雷声 发表于 2022-9-27 20:396 S1 \& [7 v- v' P, J' b8 l
    这个时间是从哪里开始算的?
    2 U( c( p: d* [我怀疑这个200多秒里面有200秒花在产生随机数上了,真正计算大概只用了2秒, ...
    ' t3 q# U$ |* \% \; k
    我不管它了,回头 linux 下换g++重新编译,顺便加上你们建议的向量化。
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    擦汗
    2024-12-25 23:22
  • 签到天数: 1182 天

    [LV.10]大乘

    9#
     楼主| 发表于 2022-9-28 00:49:59 | 显示全部楼层
    opensrc 发表于 2022-9-28 00:29* _0 d& O" s* E0 J9 E! k- F
    我有些迷糊,这样的code,难道不就应该时间差很多吗?也做了个简单的实验,你看看我做的有错吗, S6 l, K: P$ s8 C
    4 Q2 p6 d( Q) ^  b% A* x
    ...

    " q. ]/ g6 b% @. e# |你是对的,是我搞错了。确实没有优化的情况下,空循环如果次数够长本来就应该耗时较大。我搞错的原因是在不自觉得与 octave 比较,而实际上 octave 是优化过的,和是不是空循环没关系,这种不同条件的比较是没意义的。# o( k# t8 f3 N$ ~- h1 I

    " r% M% l! O. y( N% e( U雷声网友说的也对,空循环应该被编译器优化掉,我的编译器设置有问题。
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    擦汗
    2024-12-25 23:22
  • 签到天数: 1182 天

    [LV.10]大乘

    10#
     楼主| 发表于 2022-9-28 00:56:28 | 显示全部楼层
    本帖最后由 雷达 于 2022-9-28 01:09 编辑 & @% V5 R5 ?- n! w
    $ E. z# S$ c( m
    是我自己的理解有误,没有优化的情况下,空循环如果次数够长本来就应该耗时较大。
    " I8 ]# o; v' J" o有空时我会试试 SIMD和并行,看看能提高多少。, n( E4 l, J7 l( Z; I: ~2 H* B8 S" \
    过去7、8 年没有正经用C++ 写过东西,没有 sense 了 5 ]/ n) h% y% f. _; H
    谢谢大家的讨论,I learded a lot.  红包已发  
    + |# q8 a, h  H6 \  ~5 `0 W+ Z
    & N4 O3 V1 r# T) o7 q
    ; u' t+ }; g" Z! X% R. _: E. U# S0 ]/ U) h, M7 v
    2 p0 l6 Z9 ?( n
    回复 支持 反对

    使用道具 举报

    手机版|小黑屋|Archiver|网站错误报告|爱吱声   

    GMT+8, 2025-7-3 06:26 , Processed in 0.042414 second(s), 21 queries , Gzip On.

    Powered by Discuz! X3.2

    © 2001-2013 Comsenz Inc.

    快速回复 返回顶部 返回列表