2.5系の最適化
そういえば以前にソースを読もうとして僕もこんがらかっていた部分、、、とか思い出した。
shou 2009/01/26 15:13
2.5.1でもCONSTになるけど、これはバックポートされたもんなんだろうか?
この部分って、2.5だとcompile.cあたりでassemble()->makecode()->optimize_code()と進んで、ここで最適化が行われるんだけど、二項演算子の場合
/* Fold binary ops on constants. LOAD_CONST c1 LOAD_CONST c2 BINOP --> LOAD_CONST binop(c1,c2) */ case BINARY_POWER: case BINARY_MULTIPLY: case BINARY_TRUE_DIVIDE: case BINARY_FLOOR_DIVIDE: case BINARY_MODULO: case BINARY_ADD: case BINARY_SUBTRACT: case BINARY_SUBSCR: case BINARY_LSHIFT: case BINARY_RSHIFT: case BINARY_AND: case BINARY_XOR: case BINARY_OR: if (lastlc >= 2 && ISBASICBLOCK(blocks, i-6, 7) && fold_binops_on_constants(&codestr[i-6], consts)) { // <-これ i -= 2; assert(codestr[i] == LOAD_CONST); cumlc = 1; } break;
てな感じになっていて、上記の演算子の場合にfold_binops_*()にて定数畳み込みが行われるらしい。3.0になるとpeephole.cというのが増えたそうなんだけど、こっちは良く知らない。そのうち読もう読もうと思っていながらたぶん忘れる><
しかし、こういう方式だから、
>>> def foo(): ... return 1+5*3 ... >>> dis.dis(foo) 2 0 LOAD_CONST 1 (1) 3 LOAD_CONST 4 (15) 6 BINARY_ADD 7 RETURN_VALUE
のようになる。なんだかなあ。。。
#これは3.0でも同じっぽい。インタプリタに定数伝播はムチャなのかな。他を知らない・・・
追記:
そんなわけで、実は西尾さんとこで出ていた割り算が最適化された、というのはむしろ3.0の割り算デフォルトがTrue Divideになった副作用。実際2.5でも from __future__ import divisionすれば最適化されるはず。