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 sage-support@googlegroups.com
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
-~----------~----~----~----~------~----~------~--~---

Reply via email to