Movatterモバイル変換
[0]ホーム
Which happens first?
Tim Peterstim.one at home.com
Sun Apr 8 00:52:20 EDT 2001
[Carlos Alberto Reis Ribeiro, staring at the disassembled Python bytecodes for ( 16 * ( 15j + ( 4.2 - 3.9 ) + 20 ) / -2 ) % 5]> ...> 4) Now the ugly part. At [25], we load a constant (with the value 2),> and then do a unary minus operation. The question is, does it really> need to be so?No, not really.> There is any good reason not to optimize this, making the conversion> to the negative value in the compiler?The Python compiler does no classic optimizations of any kind at all:expressions are evaluated strictly left-to-right, parentheses are alwayshonored, your code is never moved, shared, rearranged, rewritten orcollapsed. WYSIWYG. Most of the time <wink>.Because it does no optimizations, there's no supporting machinery for *doing*optimizations either, so "the first one" it tries is going to be more of apain than you imagine. In particular, negative integer literals don't existin Python's grammar (only non-negative integer literals exist), and Pythoncompiles straight from parse tree to bytecode. So even that trivial littleoptimization would require a (non-existent) peephole optimizer doing patternmatching on the parse tree or bytecode stream.Not worth the effort to anyone so far. To the contrary, the utter lack ofoptimization has saved people countless hours in not needing to track downoptimization bugs <0.3 wink>.> 5) Other strange thing: at least in this example, the compiler did> not made any optimization on constant expressions.Right, and it never does. This isn't C, and Python assignments aren'tmacros, so doing stuff likeTOTAL_BYTES = BYTES_PER_SECTOR * SECTORS_PER_TRACK * NUM_TRACKSat module level is a one-time module import cost, no matter how oftenTOTAL_BYTES is dynamically referenced later. But, yes, doing that inside aloop is a Possibly Poor Idea.> ...> 1) Avoid any unnecessary calculation, specially inside tight loops.I'd amend that to "but only inside tight loops". For typical code, it reallydoesn't matter elsewhere.> I tend to use lots of explicit calculations, in order to make code> easier to understand. Things like adding/subtracting one, or> calculating an offset for a struct, for instance) are common> applications of this idiom, for example:>> >>> p = a[(3*4+2)-1] # get the second byte of the third DWORDI'll take your word for it that you find that easy to understand <wink>. Butnote that since Python doesn't have pointers, Python code is blissfully freeof fiddly pointer and offset calculations, unless you're faking high-leveldata structures by hand (in which case you're not really programming inPython anyway ...).> 2) If your expression involves value of mixed types, check> *carefully* the sequence of the calculation.That's crucial advice in any language.> It is possible to optimize the evaluation a little bit by moving> the more complex (and slower) types to the end of the evaluation.More important is that the order of coercions yield a *correct* result. Whenyou first inject a float or complex into a calculation can have profoundeffects on the numerical result, not just on the speed. Optimizing for speedis darned tricky too. For example, floating multiplies may be *much* fasterthan int multiplies in Python, because Python checks the latter for overflowbut gets no help on that from C: Python's code for multiplying two (small,not unbounded) ints slobbers over 100 lines of C!don't-worry-about-speed-until-you-have-to-ly y'rs - tim
More information about the Python-listmailing list
[8]ページ先頭