爱吱声

标题: C++ 提速的新发现 [打印本页]

作者: 雷达    时间: 2022-9-24 22:54
标题: C++ 提速的新发现
C++ 比 Octave 慢好多,怎么破?2 r  @1 r  c1 O% {% _- x/ v

/ Y" A& Q4 a% W自相关两层循环,内层循环涉及浮点数计算,试验了一下把内层循环内部全都 comment out 只留个壳子,  但空的内层循环本身就把速度拉下来了,看来问题并不在浮点计算。
: ]+ q) d& y$ e  h4 [
3 [: a( f" T1 M速度优化问题真的很有意思啊。7 B+ H* z0 Q' J( P+ B* _: E

& Z# W! L7 W$ L5 L7 v9 F欢迎大家继续讨论
作者: 数值分析    时间: 2022-9-24 23:04
拉下来?拉多少?
/ F. o' r5 a4 o* \6 n# `, X8 |把代码贴上来看看?
' ~4 z' V- H7 J- l1 x& H& u7 E! `
难道分支预测不准破坏流水线执行?不该啊。
作者: 沉宝    时间: 2022-9-24 23:15
会不会代码本身的缺陷阻止了自动优化?另外,硬件配置和开发环境可能也有关系。
作者: 风雨无阻    时间: 2022-9-24 23:33
Maybe Debug mode?
作者: 雷达    时间: 2022-9-24 23:54
本帖最后由 雷达 于 2022-9-24 23:57 编辑
# L0 {2 ?+ J, _3 ?
数值分析 发表于 2022-9-24 23:04
+ t* `3 I; z+ @# C  [; O拉下来?拉多少?
  Q/ a7 n/ T/ Y( h* v6 h把代码贴上来看看?

9 x- M& `/ x7 m% N- a) Y9 O$ i& b0 f$ ]0 @
void xcorr(comp* outcomp, comp* A, int lenA, comp* B, int lenB)
. s1 a. m+ l! f. U/ Z7 f{  {* n" L7 H/ \3 @1 P; _1 D
        comp temp, xtimesy;9 s- z9 `" ^/ P2 n: E5 @& X9 E( H
        xtimesy.re = 0;- q- @1 A$ y! Z- w: O' j' A# Y. h
        xtimesy.im = 0;
( B9 A" y+ v, N        int j0 = lenB - 1;  b8 n9 g+ o1 Q/ u# r, \' |
        int    i, j, i1, reali;& q& E& K, D/ ]  e1 N
        if (lenA % 2 == 1)! o* N( |6 a$ H* r8 D
                reali = lenA + 1;0 a/ W5 \2 W1 }( C$ g( n
        else. }. A7 y! z5 X3 u" M  o; r
                reali = lenA;
: N( ?, J+ I. d1 O        reali /= 2;
. p' X: C1 F3 e7 I" Y- P5 C% @! _/ S+ H) ]) A
        int nconv = reali + lenB;
+ @+ b+ \# k! F  \: k' ]        //#pragma omp parallel for9 ?4 s- X4 E0 z
        for (i = reali; i < nconv; i++)- |  {6 S& t4 o1 C6 c& X
        {
& v* O& U- {4 {: g& o0 S( n                temp.re = 0;
7 c4 R* `  B3 v                temp.im = 0;# Q1 ^5 Z# }8 N- _1 E% v
                i1 = i;
. r3 }: R5 K' [5 x                for (j = j0; j >= 0; j--)5 B& G' K6 O. Z) w# W
                {
6 @& `* v; E& F. a                        /* floating date operation */& R( _/ _1 V% K. ~; X4 O
                }

" P3 J- ~) j& p, P        }
6 g: }* d: L1 c( L8 Q1 `}
+ h0 T# G2 ?. t6 O  v5 G% k& W, ?) _& m" n+ ~! ~+ B
xcorr函数代码如上,comp是复数struct, 做过长度为11、19两个矢量的测试,和octave结果完全一样
* X! V& x9 @) u
0 o9 |5 I. ]$ J/ {3 k红色部分是内循环,现在其内部操作都comment out 了, j0大概是 6000。
5 R2 P; b- c( m* R' b: ?3 v现在call xcorr 100次,耗时78s.0 A3 v( y7 V) C+ r

4 d* h* h) o- [7 c2 a- i4 h如果把红色部分内循环本身完全comment out, call xcorr 1000次,耗时 <1s. / a+ u% h3 W* L+ _/ I
* C% {0 u+ ?/ G( I: n* I

作者: 雷达    时间: 2022-9-25 00:17
风雨无阻 发表于 2022-9-24 23:333 I! Q3 p( |( f8 b
Maybe Debug mode?

. Q8 P5 f( @) K9 q4 |) S
1 S. M5 |; z3 ?, g不应该,看我上面的回复。1 d( p7 P4 w. S. B

, u$ I' u/ s3 q/ k( e我更怀疑是 VS 社区版的问题
作者: 数值分析    时间: 2022-9-25 00:20
本帖最后由 数值分析 于 2022-9-25 00:24 编辑
9 t/ e4 b, `$ T6 x
雷达 发表于 2022-9-24 23:54
" B) Y; {/ Z7 T9 T/ N7 uvoid xcorr(comp* outcomp, comp* A, int lenA, comp* B, int lenB)& ?: m- g5 r( |+ J$ j2 E1 P+ U5 q; F
{! y, Y& [0 k" M. c: b
        comp temp, xtimesy;
6 k  N& I& J* q5 C; ]' R+ C7 {
4 J" ]/ f3 Y! B2 i: u
这个不是这么比的吧。。。( X) M7 A( h  m, h3 w7 _  c

  J, C" |0 Q$ \您这个函数,不带内循环的话,汇编完总共操作也没几个(不到100个)。; t+ Z; W1 F. z: G7 C# S% b8 z# N

; i% I9 |* y) |3 p而加上内循环,光jmp和dec指令就至少多执行了6000个,慢个几十倍不是正常的么?
作者: 雷达    时间: 2022-9-25 00:46
本帖最后由 雷达 于 2022-9-25 01:09 编辑
4 l" o4 T: o! \) z
数值分析 发表于 2022-9-25 00:20+ N0 y  E; ~( D( W. n$ Z
这个不是这么比的吧。。。
, V1 j1 ?7 ~- T/ E. [& A" k. t2 {  w
您这个函数,不带内循环的话,汇编完总共操作也没几个(不到100个)。

8 f2 a, W4 F9 |
9 u& r0 A) n$ L' {. b8 S/ b有道理。% y; Y. m/ @" a& \5 a/ C9 _
所以存在内循环速度就上不去,把内循环取消,改成两个向量直接点乘再求和应该就会好得多,记得 numeric 库里有算向量内积的,我回头试试。
; n4 p/ s! u* W. n. \/ n! c
- B6 `- Y; \6 u. m' Y我先尝试尽量用标准库,一个小程序,不想搞得太复杂。多谢了
作者: 沉宝    时间: 2022-9-25 01:27
雷达 发表于 2022-9-25 00:46
8 X- a$ p& {. W% G$ ^6 p# O* a; }有道理。
) L* z( y& A+ \# x* u# I/ ]; E所以存在内循环速度就上不去,把内循环取消,改成两个向量直接点乘再求和应该就会好得多,这大 ...
* _  Q; Y' L0 \/ s
你两个试验之间就差了一个空循环, call 1000次按理不会有秒级差异,可能还是编译器优化的问题。举个例子,把循环本身翻译成机器指令loop或dec/jnz,两者速度上会差很多: g' I( K2 Q/ l0 v$ j4 p+ ]3 Y
Why is the loop instruction slow? Couldn't Intel have implemented it efficiently?
作者: 沉宝    时间: 2022-9-25 01:48
数值分析 发表于 2022-9-25 00:20
+ h9 C% n, S# k4 |8 `这个不是这么比的吧。。。# n+ s: o; }. v0 ~3 w0 l( ?

# [; @) i/ y* x' ?) G4 t0 F您这个函数,不带内循环的话,汇编完总共操作也没几个(不到100个)。
而加上内循环,光jmp和dec指令就至少多执行了6000个

0 e- r/ r) E( S  L0 Z% e: O
3 ]1 p2 L! g0 N- N现在的CPU,可以把判断、jmp和dec指令全部融合进一个µOp(微操作,CPU内部流水线上的执行单位)。如果循环这样跑,花不了多少时间。
作者: 数值分析    时间: 2022-9-25 02:06
本帖最后由 数值分析 于 2022-9-25 02:16 编辑
( r' T" l3 ~/ |6 \6 w: m) T
沉宝 发表于 2022-9-25 01:48
* B9 T( [8 u$ S6 T' l/ W现在的CPU,可以把判断、jmp和dec指令全部融合进一个µOp(微操作,CPU内部流水线上的执行单位)。如果 ...

: d( x! x" w, S# F; A! m' t) M! R6 ~
是的,兄台说的对。
( G. k0 Q5 {% m
7 C, Z" m: o0 ?: Z! H, e  g其实我想说的是 真正数值计算部分和代码中其他不直接计算的overhead的比值这个事儿。
1 x' m( t" k! I2 ]& I8 J, x5 }# j; r
雷达兄构造测试用例的时候,屏蔽掉了所有计算的部分,使得剩下的都是overhead,这样run time比较的结果就显得好像不合理了。如果把计算加回去,计算部分的run time会dominate,结果就不那么离谱了。因为不好说,所以用指令数对比的方式试图直观地说明这一点。
1 y& H* z8 J- ]0 ]4 |3 N- m8 X
) `: d; d! y5 Y' U# y比如说,如果有计算,那么跑六千个循环相对于计算应该用不了多少时间。但是如果一边是什么都不做,另一边是六千个循环,那六千个循环比什么都不做慢几十倍了,就不是那么不合理了。, x6 i! s! N; c9 f# b

% ^2 N0 b* t8 m当然也有可能像兄台说的,是优化参数的问题,但我觉得更多地是测试用例设计的不合理。
作者: 雷达    时间: 2022-9-25 04:47
本帖最后由 雷达 于 2022-9-25 04:49 编辑 2 d# @7 r! B; t9 l& p" m4 H9 Y9 |
沉宝 发表于 2022-9-25 01:276 D6 l9 G' d" c9 S* ^" P0 u- K0 k
你两个试验之间就差了一个空循环, call 1000次按理不会有秒级差异,可能还是编译器优化的问题。举个例子 ...

( T; G8 p/ m8 D' a! a6 K
( |% J* a6 [1 X; B0 Q8 I又写了个小实验,没有调用子函数,双层循环,外层6千次,内循环30万次空转,有或没有空转内循环,时间差一倍,我上面这个差的太多了。
# \+ O0 F! P7 @
) n0 n& G0 E; Z) ?. Z' y4 ?& m我已经完全懵了。
作者: 沉宝    时间: 2022-9-25 05:51
雷达 发表于 2022-9-25 04:47
3 D- x) I/ I% E: l; q) P又写了个小实验,没有调用子函数,双层循环,外层6千次,内循环30万次空转,有或没有空转内循环,时间差 ...
6 h  L( `" Q- y0 P5 M3 R5 {7 X$ }$ c
时间差一倍的结果可以接受。/ z5 N. e) i8 `$ T8 s

. c' u; O) q, O/ u你还是用profile工具看看吧。现在大家都主观瞎猜。
作者: 数值分析    时间: 2022-9-25 14:58
本帖最后由 数值分析 于 2022-9-25 15:38 编辑 + x' ^: k. Z8 X
雷达 发表于 2022-9-25 04:47
0 @$ B% j1 m0 m* p又写了个小实验,没有调用子函数,双层循环,外层6千次,内循环30万次空转,有或没有空转内循环,时间差 ...
2 I! w# S! d& X
5 a1 y/ R  K, J0 Y
7 {3 K* o1 C6 i& w9 `
; c- W, V- i) }4 j6 H' L. D8 U) b" H9 E
能不能把这个也贴上来,看看和上一个有什么不同?
作者: 雷达    时间: 2022-9-26 01:30
本帖最后由 雷达 于 2022-9-27 01:17 编辑 ) @, J  J9 E! {9 `8 {
数值分析 发表于 2022-9-25 14:58
; J* }& r8 [  K  i& S% L' _; o! j, _能不能把这个也贴上来,看看和上一个有什么不同?
3 m8 B6 h( k+ I7 o0 ~8 L
理了理思路,重新做了一个测试。
5 P: U1 J( ?+ x2 k做了两个 vector 和 两个 float *, 都长 100000
. i+ K2 N) _1 m外循环 6000,里面先做随机数生成,模拟真实环境,避免数据的 cache.
  i& P$ f( p. u7 F( X  u" }% F% L
8 w$ S( a7 d  `8 Q内循环试了4种方法,
( h# ~+ V  K- h6 d1. 直接调用 vector inner_product 247s
9 G6 L; R, L5 O2. vector 循环点乘累加 237s- l  g7 c5 g* @/ k8 a& H' i
3. float * 循环点乘累加 204s
1 i# l/ z: W0 _4. 空循环 100000 次 202s
! r$ `# h, Y" V
  L5 D, e8 B4 F: |2 w% r不做内循环 200s) D8 [# X% v7 J8 K) e8 _* t
$ J  \6 W- v8 u, x, ~4 _- ^' ]  C
你昨天说的对,内循环本身占比是很小的,大头在其他处理。
& ]% ^8 U0 I% j: d3 n) x* k  h7 m另外可以看到, float * 循环点乘累加 并不差,比用vector 还更快。
$ A2 q& p) E) z% i1 h
% K; I* [: s6 \2 u6 J至于我那个原始程序,还有一些疑问,见5楼,其他都不变仅仅是有无空的内循环就有很大不同,这是不对的,也许有一些其他缺陷我没有看到。(也许可以改成 while 试试)1 q  h- {% V- @
& ^% O% A  P  r2 {; ^- i2 [0 V
(为什么下面我贴的  b1 加 方括号里的 i , 显示出来却是 b1 ?方括号 i 消失了。 LOL . 改成  jj 好了,原来 方括号里的 i 是斜体标志  LOL)" ^1 Q+ R2 b" ^0 j% f
) w: l, P6 o8 B9 H/ @+ _
        std::vector < float > vec1(N);. V( n& @' e" J4 {" q
        std::vector < float > vec2(N);
/ [2 n7 k: R: {8 X- c6 u% |$ E        float* b1 = new float[N];
3 r  z  E: D, }" J        float* b2 = new float[N];" {# j& G0 I5 c7 j% X
+ u0 j" \6 d6 X3 I- Y
        for (int j = 0; j < 6000; j++)' i( d) Z8 o7 c& V
        {; h' B+ c7 q& Q# [: Q9 l4 }
                std::generate(vec1.begin(), vec1.end(), []() {
+ A9 k5 d6 d2 g                        return static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / 23.23));;( [( e% }/ ~# o1 |
                        });
. _- k: ^: Z+ b- p+ x% W* N# Q4 C. J4 u) q  {" y7 l
                std::generate(vec2.begin(), vec2.end(), []() {
' b/ S3 D- n% }: u# O                        return static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / 24.31));;
2 b5 A& Z. K; |9 n2 f! G7 v                        });- {  `4 }* z% K

$ k9 {+ _' o6 R; t/ q$ p  p                for (size_t jj = 0; jj < vec1.size(); jj++)6 ^& B1 i- ~7 R4 s& P) R
                {
7 e" C" d3 Q) O1 j6 y                        b1[jj] = vec1[jj];
0 i% m5 I7 h, i                }7 A* d; T8 w! n8 q( j7 `2 O4 ?

1 [5 M& ~1 i9 |; C                for (size_t jj = 0; jj < vec2.size(); jj++)
- R1 v% [& v  g                {
: w& H: M& `7 D4 b                        b2[jj] = vec2[jj];
0 @) l  b' Q) Y% f* e% ?                }
# P( ^. i1 ~. Z3 D1 x3 B/ h$ _' w& Q& g$ e4 A6 E! \
                //Method - 1  N=100000 247s  * j4 {% k% `% T0 {. U
                //fresult = inner_product(vec1.begin(), vec1.end(), vec2.begin(), 0);+ S2 f" `3 D% m& G' o
                                8 V; K) z7 a$ m4 I% V
                //Method - 2  N=100000  237s8 n; S$ u2 n' o6 D
                /*" m, [( y( m. J8 s/ g
                for (int jj = 0; jj < N ; jj++)
9 q5 C! L  k  m  m/ E( n8 d                {
9 h1 k9 i& _; J1 l/ H+ k9 ^                        fresult += vec1[jj] * vec2[jj];
$ H4 l" y, T  X                }
# `0 `4 _/ F9 H0 k1 a8 g5 H7 a                */
( r: a* Z9 H+ ^! {; |3 h$ N                                5 E. y7 L) |- H% a7 @5 V" n
                //Method - 3  N=100000 204s7 ]/ l8 k- W  X8 f& G% ?  l
                /*
$ t. |9 X2 a4 z2 P( P7 c0 c                for (int jj = 0; jj < N; jj++)6 ]3 ?2 J5 j8 v
                {9 x4 G4 C1 n4 ]
                        fresult += b1[jj] * b2[jj];  o5 c. C* }6 n3 R1 }4 W8 e
                }
: a! ?/ o5 L2 s8 o% g                */- a: `2 _6 m6 p6 i& n$ H* I
0 Q2 N3 |: [; o/ r
                //Method - 4   202s
$ i, ~5 l: e! ^/ z, s: {) h6 m                /*6 u8 ]( ^/ K* D& n
                for (int jj = 0; jj < N; jj++)
. f# R8 q! B0 W% S3 o                {
/ c) H7 z' @. ~                        5 D9 a% f2 e) J- K
                }8 S' ?/ r& J9 o
                */
* S* l: @" G- g0 p                //comment out all methods, N=100000  202s               
/ s% n9 U4 D& a, Y- ]        }3 k  b4 [& i  ]

( r! Y+ u% @1 s9 C        delete []b1;2 m3 l* \8 j# b; N. c8 |; z
        delete []b2;

2 X" Q5 b8 L5 c: i* Y0 K& _0 v* b
作者: 机器猫    时间: 2022-9-27 00:15
瞎猜一下啊。把第一个的那个j定义成register变量会不会有不同?
( s7 ~; A$ e+ c
+ R0 c( x* q# d1 J6 a, T) A你第二个试验里面的j在循环里面又重新定义了啊,你确定真的跑了6000次?
* @" a  w" k5 ?# w- R( b" w, {. {' q
作者: 雷达    时间: 2022-9-27 01:16
机器猫 发表于 2022-9-27 00:15
/ r8 [% o8 [  k) H( Z) \( Y9 V& A瞎猜一下啊。把第一个的那个j定义成register变量会不会有不同?0 |! I$ }+ F: n* G
3 R" ?/ y1 [: t6 s! M9 ?3 ~
你第二个试验里面的j在循环里面又重新定义 ...
3 B2 q( u0 V8 X/ d; V& d! F
内循环里面的 j 实际是 i, 为了规避爱坛显示的冲突帖子里临时改成了j, 现在是 jj 了。好累 、LOL- J' ]: _6 L, F5 ]( H! ^
0 Q: W6 B1 o5 A# J" A
不和它较劲了,瞎耽误工夫,我已经转到 ubuntu, 也准备顺便试试 avx2 向量化。
作者: 机器猫    时间: 2022-9-27 02:06
雷达 发表于 2022-9-27 01:16# U9 E6 y* M2 S& i, v) N, b% X. Y
内循环里面的 j 实际是 i, 为了规避爱坛显示的冲突帖子里临时改成了j, 现在是 jj 了。好累 、LOL
8 i: G# r2 Q$ H! s* D5 U7 H2 k6 b
不和它 ...

8 B7 A( w. y, g' {( P3 I" ~- d  f* z& F$ u5 E
不过可以试试我说的register变量。前一个试验j是混在一堆其它变量里一起定义的,很有可能是在stack上,这样内存读写会更多,要是再碰上每次都需要加载cache就更慢了。
( c" i7 w/ h6 W6 I* D2 m后面一个是在循环那里定义的,说不定编译器就把它优化成register变量了
作者: opensrc    时间: 2022-9-27 07:25
一个无关问题,为什么爱坛的帖子里在我这里有好些奇怪的东东在里面,是防拷贝措施吗?
作者: 雷声    时间: 2022-9-27 20:29
雷达 发表于 2022-9-24 23:54& R: R: z) y2 I% L
void xcorr(comp* outcomp, comp* A, int lenA, comp* B, int lenB)# Q2 z9 L$ m3 P' m* g' _' t2 i3 d
{: v5 I$ ?3 n- u
        comp temp, xtimesy;
8 X/ D6 y5 U- J2 U; t
这个code里面如果Openmp没有被注释掉的话,那么temp那个变量应该是定义在循环里面,否则线程之间会存在争夺写入那个temp的风险。
+ t% d. S7 A7 ?0 w6 P内层for循环如果没有内部操作的话,编译时应该被优化掉了,和你完全注册掉整个循环是一回事。可能你的编译设置没有打开优化?
* G* s$ L/ Y! J) L  _  f; zVS社区版没有问题,我工作用的就是社区版,设置正常的话不会比商业版差。以前游说头头用Intel Compiler,他说不想花钱,而且差不了多少,就一直用到现在。
作者: 雷声    时间: 2022-9-27 20:39
雷达 发表于 2022-9-26 01:30
% V5 s, G7 v7 m理了理思路,重新做了一个测试。( `, T4 `8 Z( ~1 O( |4 q
做了两个 vector 和 两个 float *, 都长 100000
' y$ a3 v% u3 u9 A外循环 6000,里面先做随 ...
' h# k. ]9 i, u
这个时间是从哪里开始算的?
0 h( c) ], ]/ p1 p$ G& L5 J我怀疑这个200多秒里面有200秒花在产生随机数上了,真正计算大概只用了2秒, 用了vector那个因为有vector的额外开销,多了几十秒。4 ]4 z) F& {2 g# {1 u1 ]
按照两个10万个数字的相关计算的规模来估计的话,两秒都算很长很长了。这个结果真的很奇怪。
作者: 雷达    时间: 2022-9-27 22:41
雷声 发表于 2022-9-27 20:39
, O$ ^& N$ e; K$ `( r这个时间是从哪里开始算的?
) `& X6 o3 I( U$ L我怀疑这个200多秒里面有200秒花在产生随机数上了,真正计算大概只用了2秒, ...
# f" j% a" o7 x) K$ Q4 y
我不管它了,回头 linux 下换g++重新编译,顺便加上你们建议的向量化。
作者: 四处张望    时间: 2022-9-28 00:12
你这个循环主要的计算时间是那个rand,这个循环本身占用时间微乎其微。9 r9 o8 \+ z( S+ @+ v/ C$ z# l
你的空循环,如果是现在的代码,编译器很可能完全不生成对应代码,因为没有任何输出或者修改变量,所以可以看到时间都是202S。你可以认为啥都不干的时间就是那么多。
( B0 C5 O" w. z4 T1 i+ I: [9 Z与此对应用数组(指针)花了2S7 u% l2 l5 o7 y+ W" L
你用vec1[jj]*vec2[jj]理论上不应该差30多秒,这里很可能是你对vector的操作带来了内存操作,你可以试试把初始化挪出循环然后再比较,理论上vector的随机访问和数组应该几乎没什么区别。
作者: opensrc    时间: 2022-9-28 00:29
雷达 发表于 2022-9-24 23:54, Q9 m2 z6 F+ _" u+ ], N& E
void xcorr(comp* outcomp, comp* A, int lenA, comp* B, int lenB)
9 W1 ~" X/ H% p( D{+ C+ ~! ]$ [$ g
        comp temp, xtimesy;

& A! ^' ^! C1 U# e2 _9 h我有些迷糊,这样的code,难道不就应该时间差很多吗?也做了个简单的实验,你看看我做的有错吗2 L: P( W( o2 H  U6 M) M8 H
8 |: ^( t+ b( a6 i. G

作者: 雷达    时间: 2022-9-28 00:49
opensrc 发表于 2022-9-28 00:29. s0 w  L" E5 W
我有些迷糊,这样的code,难道不就应该时间差很多吗?也做了个简单的实验,你看看我做的有错吗
. w# L: S! T" o2 j* `5 m/ c" A; R/ W1 F
...

' y$ K1 C2 U0 V. H! p你是对的,是我搞错了。确实没有优化的情况下,空循环如果次数够长本来就应该耗时较大。我搞错的原因是在不自觉得与 octave 比较,而实际上 octave 是优化过的,和是不是空循环没关系,这种不同条件的比较是没意义的。) \) I3 [1 A+ S2 Y7 \% {
% \; H" L  B3 G
雷声网友说的也对,空循环应该被编译器优化掉,我的编译器设置有问题。
作者: 雷达    时间: 2022-9-28 00:56
本帖最后由 雷达 于 2022-9-28 01:09 编辑 ( @" U9 m$ Q) X* q/ G; V/ E& {
: P$ K( H0 A9 ^+ i& }
是我自己的理解有误,没有优化的情况下,空循环如果次数够长本来就应该耗时较大。; ^# g) ]5 a% U2 X$ L  `3 Q1 d
有空时我会试试 SIMD和并行,看看能提高多少。
# b" o$ B: y" s( D: }, C过去7、8 年没有正经用C++ 写过东西,没有 sense 了
/ X* T. [8 @6 a; S6 A谢谢大家的讨论,I learded a lot.  红包已发  ' X9 m4 P0 x; ~. v& M2 e" Y

+ i$ k9 _3 s4 s, G7 J
& P: V' l) k1 U) P$ Z) q: W2 w+ s' Z/ b
( G: P. u2 C( a4 L! `





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