On Oct 21, 2008, at 10:17 PM, pong wrote:
> Thanks to both Dan and William. However, Dan's result puzzled me.
> Aren't they suggested that the for loop is faster?
>
> Here is what I got:
>
> sage: timeit('list(2*vector([random() for j in range(10)]))')
> 625 loops, best of 3: 332 µs per loop
> sage: timeit('[2*random() for j in range(10)]')
> 125 loops, best of 3: 8.3 ms per loop
A more precise benchmark (ignoring vector/list creation) would
probably be:
sage: L = [random() for j in range(10)]
sage: v = vector(L)
sage: timeit("2*v")
625 loops, best of 3: 1.76 µs per loop
sage: timeit("[2*a for a in L]")
25 loops, best of 3: 29.2 ms per loop
To explain your timings, note
sage: parent(random())
<type 'float'>
sage: parent(vector([random() for j in range(10)]))
Vector space of dimension 10 over Real Double Field
sage: parent(2)
Integer Ring
In your first loop, it's creating a RDF vector and then multiplying
by 2 via
sage: cm = sage.structure.element.get_coercion_model()
sage: cm.explain(2, v)
Action discovered.
Left scalar multiplication by Integer Ring on Vector space of
dimension 10 over Real Double Field
Result lives in Vector space of dimension 10 over Real Double Field
Vector space of dimension 10 over Real Double Field
in other words, it turns "2" into an RDF, then multiplies every
element (in fast compiled code) of the RDF vector. In the second
case, it's having to re-discover the float-Integer operation each
time (as the result is a float) which happens to be the worst-case
scenario. Note with RDF rather than floats
sage: timeit("[2*a for a in v]")
625 loops, best of 3: 20.9 µs per loop
(still not the speed of a vector-element multiply, but much better).
There is a ticket or two related to improving this, e.g. #3938 and
#2898.
> which suggested otherwise. Also how does timeit determine how many
> loops to perform in a test?
In my experience (haven't looked at the code) it keeps timing until
it hits about a second, going by powers of 5.
>> Also, instead of doing your own loops, you can use %timeit:
>>
>> sage: %timeit [2*random() for j in range(10)]
>> 100000 loops, best of 3: 6.87 µs per loop
>> sage: %timeit list(2*vector([random() for j in range(10)]))
>> 10000 loops, best of 3: 112 µs per loop
Note that the 2 is not getting preparsed, and so one is doing python-
int * python-float. Also, in the second example, the bulk of the time
is in the conversion, not the multiply
sage: sage: %timeit list(2*vector([random() for j in range(10)]))
10000 loops, best of 3: 173 µs per loop
sage: %timeit list(vector([random() for j in range(10)]))
10000 loops, best of 3: 167 µs per loop
>> Using list comprehensions is almost always a good choice in Sage/
>> Python;
>> as I understand (and as we see above), they're very well-optimized.
Yes, though using vectors can be faster too, and if one's list really
is a vector than it can make much easier to read code than
manipulating lists.
- Robert
--~--~---------~--~----~------------~-------~--~----~
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/sage-support
URLs: http://www.sagemath.org
-~----------~----~----~----~------~----~------~--~---