Re: [Python-Dev] Optimizing list.sort() by checking type in advance

2016-10-11 Thread Tim Peters
[Terry Reedy]
>
> This seems like a generic issue with timing mutation methods
> ...
> But I am sure Tim worked this out in his test code, which should be
> reused, perhaps updated with Viktor's perf module to get the most
> stable timings possible.

sortperf.py is older than me ;-)  It's not at all intended to give
fine-grained timings:  it's a sledgehammer than runs each case _only
once_, to confirm/refute _big_ changes.

So it's useful qualitatively when a "big claimed change" is at issue,
but useless for quantifying beyond "wow!" or "ouch!" or "meh".

Since this is a "big claimed change", a "wow!" outcome is good-enough
confirmation.  And a "meh" outcome would be almost good enough for
cases where the new specializations don't apply - although I haven't
seen any numbers from sortperf.py for those cases yet.  I expect a
"meh" outcome for those, based on reasoning - but may be surprised by
reality.
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Optimizing list.sort() by checking type in advance

2016-10-11 Thread Terry Reedy

On 10/11/2016 10:26 AM, Chris Angelico wrote:


After the first call, the list will be sorted. Any subsequent attempts
will use the sorted list.


This seems like a generic issue with timing mutation methods.  Is the 
mutated output suitable input for another mutation.  With list.reverse, 
the output is suitable.  Ditto for other permutations that are 
independent of the data, including random.shuffle.  With list.pop, the 
number of mutations has to be limited to the length of the list.  With 
list.sort, the list needs to be 'restored' -- either copied or shuffled 
each time.  So it seems that one is stuck with timing 'restore', restore 
+ sort_a, restore + sort_b, subtracting the timing for restore, and 
comparing.  But I am sure Tim worked this out in his test code, which 
should be reused, perhaps updated with Viktor's perf module to get the 
most stable timings possible.


--
Terry Jan Reedy

___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Optimizing list.sort() by checking type in advance

2016-10-11 Thread Paul Moore
On 11 October 2016 at 15:32, Elliot Gorokhovsky
 wrote:
> But the sort mutates F...does the setup get executed each time? I thought
> it's just at the beginning. So then F gets mutated (sorted) and subsequent
> sorts time wrong.

Did I not say earlier - sorry. I'm suggesting that you put each timing
run into a separate Python process.

# Optimised code
python -m perf timeit -s "from mymod import FastList; L=;F=FastList(L)" "F.fastsort()"
# Core sort routine
python -m perf timeit -s "L=" "L.sort()"
# Or maybe, if FastList exposes the existing sort function as well
# Non-optimised code
python -m perf timeit -s "from mymod import FastList; L=;F=FastList(L)" "F.sort()"

Paul.
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Optimizing list.sort() by checking type in advance

2016-10-11 Thread Elliot Gorokhovsky
But the sort mutates F...does the setup get executed each time? I thought
it's just at the beginning. So then F gets mutated (sorted) and subsequent
sorts time wrong.

On Tue, Oct 11, 2016, 7:51 AM Paul Moore  wrote:

> On 11 October 2016 at 14:04, Elliot Gorokhovsky
>  wrote:
> > Right, that sounds good, but there's just one thing I don't understand
> > that's keeping me from using it. Namely, I would define a benchmark list
> L
> > in my setup, and then I would have code="F=FastList(L);F.fastsort()". The
> > problem here is I'm measuring the constructor time along with the sort
> time,
> > right, so wouldn't that mess up the benchmark? Or does timeit separate
> the
> > times?
>
> That would mess up your times. Put F=FastList(L) in your setup.
>
> Paul
>
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Optimizing list.sort() by checking type in advance

2016-10-11 Thread Elliot Gorokhovsky
Right, that sounds good, but there's just one thing I don't understand
that's keeping me from using it. Namely, I would define a benchmark list L
in my setup, and then I would have code="F=FastList(L);F.fastsort()". The
problem here is I'm measuring the constructor time along with the sort
time, right, so wouldn't that mess up the benchmark? Or does timeit
separate the times?

On Tue, Oct 11, 2016, 2:22 AM Paul Moore  wrote:

> On 11 October 2016 at 03:15, Elliot Gorokhovsky
>  wrote:
> > There's an option to provide setup code, of course, but I need to set up
> > before each trial, not just before the loop.
>
> Typically, I would just run the benchmark separately for each case,
> and then you'd do
>
> # Case 1
> python -m perf timeit -s 'setup; code; here' 'code; to; be; timed; here'
> [Results 1]
> # Case 2
> python -m perf timeit -s 'setup; code; here' 'code; to; be; timed; here'
> [Results 2]
>
> The other advantage of doing it this way is that you can post your
> benchmark command lines, which will allow people to see what you're
> timing, and if there *are* any problems (such as a method lookup that
> skews the results) people can point them out.
>
> Paul
>
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Optimizing list.sort() by checking type in advance

2016-10-11 Thread Chris Angelico
On Wed, Oct 12, 2016 at 1:24 AM, Paul Moore  wrote:
> On 11 October 2016 at 15:00, Chris Angelico  wrote:
>> On Wed, Oct 12, 2016 at 12:51 AM, Paul Moore  wrote:
>>> On 11 October 2016 at 14:04, Elliot Gorokhovsky
>>>  wrote:
 Right, that sounds good, but there's just one thing I don't understand
 that's keeping me from using it. Namely, I would define a benchmark list L
 in my setup, and then I would have code="F=FastList(L);F.fastsort()". The
 problem here is I'm measuring the constructor time along with the sort 
 time,
 right, so wouldn't that mess up the benchmark? Or does timeit separate the
 times?
>>>
>>> That would mess up your times. Put F=FastList(L) in your setup.
>>
>> But then you're resorting an already-sorted list, which may well have
>> different timings (it certainly does in timsort).
>
> Why would it be already sorted? I assume FastList(L) is simply a
> wrapper round a normal list that has a modified sort method with the
> optimisation included.
>
> Of course, that's essentially the point here - without seeing the
> code, we're (to an extent) guessing.

After the first call, the list will be sorted. Any subsequent attempts
will use the sorted list.

ChrisA
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Optimizing list.sort() by checking type in advance

2016-10-11 Thread Paul Moore
On 11 October 2016 at 15:00, Chris Angelico  wrote:
> On Wed, Oct 12, 2016 at 12:51 AM, Paul Moore  wrote:
>> On 11 October 2016 at 14:04, Elliot Gorokhovsky
>>  wrote:
>>> Right, that sounds good, but there's just one thing I don't understand
>>> that's keeping me from using it. Namely, I would define a benchmark list L
>>> in my setup, and then I would have code="F=FastList(L);F.fastsort()". The
>>> problem here is I'm measuring the constructor time along with the sort time,
>>> right, so wouldn't that mess up the benchmark? Or does timeit separate the
>>> times?
>>
>> That would mess up your times. Put F=FastList(L) in your setup.
>
> But then you're resorting an already-sorted list, which may well have
> different timings (it certainly does in timsort).

Why would it be already sorted? I assume FastList(L) is simply a
wrapper round a normal list that has a modified sort method with the
optimisation included.

Of course, that's essentially the point here - without seeing the
code, we're (to an extent) guessing.
Paul
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Optimizing list.sort() by checking type in advance

2016-10-11 Thread Chris Angelico
On Wed, Oct 12, 2016 at 12:51 AM, Paul Moore  wrote:
> On 11 October 2016 at 14:04, Elliot Gorokhovsky
>  wrote:
>> Right, that sounds good, but there's just one thing I don't understand
>> that's keeping me from using it. Namely, I would define a benchmark list L
>> in my setup, and then I would have code="F=FastList(L);F.fastsort()". The
>> problem here is I'm measuring the constructor time along with the sort time,
>> right, so wouldn't that mess up the benchmark? Or does timeit separate the
>> times?
>
> That would mess up your times. Put F=FastList(L) in your setup.

But then you're resorting an already-sorted list, which may well have
different timings (it certainly does in timsort).

ChrisA
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Optimizing list.sort() by checking type in advance

2016-10-11 Thread Paul Moore
On 11 October 2016 at 14:04, Elliot Gorokhovsky
 wrote:
> Right, that sounds good, but there's just one thing I don't understand
> that's keeping me from using it. Namely, I would define a benchmark list L
> in my setup, and then I would have code="F=FastList(L);F.fastsort()". The
> problem here is I'm measuring the constructor time along with the sort time,
> right, so wouldn't that mess up the benchmark? Or does timeit separate the
> times?

That would mess up your times. Put F=FastList(L) in your setup.

Paul
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Optimizing list.sort() by checking type in advance

2016-10-11 Thread Paul Moore
On 11 October 2016 at 03:15, Elliot Gorokhovsky
 wrote:
> There's an option to provide setup code, of course, but I need to set up
> before each trial, not just before the loop.

Typically, I would just run the benchmark separately for each case,
and then you'd do

# Case 1
python -m perf timeit -s 'setup; code; here' 'code; to; be; timed; here'
[Results 1]
# Case 2
python -m perf timeit -s 'setup; code; here' 'code; to; be; timed; here'
[Results 2]

The other advantage of doing it this way is that you can post your
benchmark command lines, which will allow people to see what you're
timing, and if there *are* any problems (such as a method lookup that
skews the results) people can point them out.

Paul
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Optimizing list.sort() by checking type in advance

2016-10-10 Thread Greg Ewing

Elliot Gorokhovsky wrote:
I ran the 
benchmark a couple of times and the numbers seem to exactly line up 
something like one in five times; perhaps not that crazy considering 
they're executing nearly the same code?


Could this be a result of a time being measured in seconds
somewhere and then divided down?


*** 1e7 ints + 1 float (to disable the optimization while keeping the 
precheck)***
F.fastsort(): 7.57237982749939
F.sort(): 7.666172504425049


This result looks a bit suspicious too -- it's hard to see
how fastsort could be faster even when the optimisation
is not being used.

--
Greg

___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Optimizing list.sort() by checking type in advance

2016-10-10 Thread Elliot Gorokhovsky
Right - sorry about that last bit!

I couldn't figure out how to use timeit/perf for this because the list has
to be reinitialized each time it gets sorted. So with time.time() I can
just wrap the sorting and cut the initialization out (and I could always
throw it in a for loop to do it as many times as necessary). But with
timeit/perf, as I understand, you just give it a number of iterations and a
code snippet and it loops for you. So I don't see how I could get it to cut
out the initialization. There's an option to provide setup code, of course,
but I need to set up before each trial, not just before the loop.

Regardless, one could always wrap the whole contribution with a length test
and disable for lists with less than, say, 1000 elements. And though for
the above reason I couldn't figure out how to benchmark properly for small
lists, it's clear that for large lists this gives a real improvement with
very little change in the code: the fact is that it really doesn't make
sense to do all this typechecking nlogn times when we can just get it over
with once at the beginning. The cost is very, very small, as demonstrated
by the last benchmark (which is for a 1e7 list, so it is probably more
valid with my crude technique), so heterogeneous lists don't get slowed
down perceptibly.

On Mon, Oct 10, 2016 at 8:06 PM Guido van Rossum  wrote:

> So maybe someone should explain to Elliott *why* his own benchmarks
> are not trustworthy, rather than just repeat "use perf or timeit".
> Actually, there are two things: (a) when something new comes along it
> *always* needs to prove beyond a shadow of a doubt that it is actually
> an improvement and not a timing artifact or a trick; (b) you can't
> time sorting 10 values *once* and get a useful result. You have to do
> it many times. And you have to make sure that creating a list of 10
> random values isn't taken as part of your test -- that's tricky since
> random() isn't all that fast; but it has to be done.
>
> Although Elliott had it coming when he used needlessly offensive
> language in his first post.
>
> On Mon, Oct 10, 2016 at 5:09 PM, Steven D'Aprano 
> wrote:
> > On Mon, Oct 10, 2016 at 09:16:32PM +, Elliot Gorokhovsky wrote:
> >
> >> Anyway, benchmarking technique aside, the point is that it it works well
> >> for small lists (i.e. doesn't affect performance).
> >
> > You've been shown that there is something suspicious about your
> > benchmarking technique, something that suggests that the timing results
> > aren't trustworthy. Until you convince us that your timing results are
> > reliable and trustworthy, you shouldn't be drawing *any* conclusions
> > about your fastsort versus the standard sort.
> >
> >
> > --
> > Steve
> > ___
> > Python-Dev mailing list
> > Python-Dev@python.org
> > https://mail.python.org/mailman/listinfo/python-dev
> > Unsubscribe:
> https://mail.python.org/mailman/options/python-dev/guido%40python.org
>
>
>
> --
> --Guido van Rossum (python.org/~guido)
>
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Optimizing list.sort() by checking type in advance

2016-10-10 Thread Elliot Gorokhovsky
So here's a simple attempt at taking lots of measurements just using
time.time() with lists of ints. The results are great, if they are valid
(which I leave to you to judge); even for lists with just one element, it's
16% faster! The columns are length, number of trials, and percent
improvement:

Integer benchmarks
1 1000 1-fastsort()/sort(): 0.14896401672523163
5 200 1-fastsort()/sort(): 0.2915859704616376
10 100 1-fastsort()/sort(): 0.3576859149132914
1000 1 1-fastsort()/sort(): 0.3230363920681264
100 10 1-fastsort()/sort(): 0.292595011903772

And here's the benchmark script:
from fastlist import FastList
import random; random.seed(42)
from time import time

def bench_list(size,  trials):
L = [random.randrange(size) for _ in range(size)]
trials = int(trials); size = int(size)

fastlist_time = 0
for _ in range(trials):
F = FastList(L)
start = time()
F.fastsort()
fastlist_time += time() - start


defaultlist_time = 0
for _ in range(trials):
F = FastList(L)
start = time()
F.sort()
defaultlist_time += time() - start


print(size, trials,
  "1-fastsort()/sort():", 1-fastlist_time/defaultlist_time)

print("Integer benchmarks")
bench_list(1, 1e7)
bench_list(5, 1e7/5)
bench_list(10, 1e7/10)
bench_list(1000, 1e7/1000)
bench_list(100, 1e7/1e6)

Is that a valid way to benchmark the implementation?

On Mon, Oct 10, 2016 at 8:15 PM Elliot Gorokhovsky <
elliot.gorokhov...@gmail.com> wrote:

> Right - sorry about that last bit!
>
> I couldn't figure out how to use timeit/perf for this because the list has
> to be reinitialized each time it gets sorted. So with time.time() I can
> just wrap the sorting and cut the initialization out (and I could always
> throw it in a for loop to do it as many times as necessary). But with
> timeit/perf, as I understand, you just give it a number of iterations and a
> code snippet and it loops for you. So I don't see how I could get it to cut
> out the initialization. There's an option to provide setup code, of course,
> but I need to set up before each trial, not just before the loop.
>
> Regardless, one could always wrap the whole contribution with a length
> test and disable for lists with less than, say, 1000 elements. And though
> for the above reason I couldn't figure out how to benchmark properly for
> small lists, it's clear that for large lists this gives a real improvement
> with very little change in the code: the fact is that it really doesn't
> make sense to do all this typechecking nlogn times when we can just get it
> over with once at the beginning. The cost is very, very small, as
> demonstrated by the last benchmark (which is for a 1e7 list, so it is
> probably more valid with my crude technique), so heterogeneous lists don't
> get slowed down perceptibly.
>
> On Mon, Oct 10, 2016 at 8:06 PM Guido van Rossum  wrote:
>
> So maybe someone should explain to Elliott *why* his own benchmarks
>
> are not trustworthy, rather than just repeat "use perf or timeit".
>
> Actually, there are two things: (a) when something new comes along it
>
> *always* needs to prove beyond a shadow of a doubt that it is actually
>
> an improvement and not a timing artifact or a trick; (b) you can't
>
> time sorting 10 values *once* and get a useful result. You have to do
>
> it many times. And you have to make sure that creating a list of 10
>
> random values isn't taken as part of your test -- that's tricky since
>
> random() isn't all that fast; but it has to be done.
>
>
>
> Although Elliott had it coming when he used needlessly offensive
>
> language in his first post.
>
>
>
> On Mon, Oct 10, 2016 at 5:09 PM, Steven D'Aprano 
> wrote:
>
> > On Mon, Oct 10, 2016 at 09:16:32PM +, Elliot Gorokhovsky wrote:
>
> >
>
> >> Anyway, benchmarking technique aside, the point is that it it works well
>
> >> for small lists (i.e. doesn't affect performance).
>
> >
>
> > You've been shown that there is something suspicious about your
>
> > benchmarking technique, something that suggests that the timing results
>
> > aren't trustworthy. Until you convince us that your timing results are
>
> > reliable and trustworthy, you shouldn't be drawing *any* conclusions
>
> > about your fastsort versus the standard sort.
>
> >
>
> >
>
> > --
>
> > Steve
>
> > ___
>
> > Python-Dev mailing list
>
> > Python-Dev@python.org
>
> > https://mail.python.org/mailman/listinfo/python-dev
>
> > Unsubscribe:
> https://mail.python.org/mailman/options/python-dev/guido%40python.org
>
>
>
>
>
>
>
> --
>
> --Guido van Rossum (python.org/~guido)
>
>
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Optimizing list.sort() by checking type in advance

2016-10-10 Thread Tim Peters
[please restrict follow-ups to python-ideas]

Let's not get hung up on meta-discussion here - I always thought "massive
clusterf**k" was a precise technical term anyway ;-)

While timing certainly needs to be done more carefully, it's obvious to me
that this approach _should_ pay off significantly when it applies.
Comparisons are extraordinarily expensive in Python, precisely because of
the maze of test-and-branch code it requires just to figure out which
bottom-level comparison function to invoke each time.  That's why I spent
months of my life (overall) devising a sequence of sorting algorithms for
Python that reduced the number of comparisons needed.

Note that when Python's current sort was adopted in Java, they still kept a
quicksort variant for "unboxed" builtin types.  The adaptive merge sort
incurs many overheads that often cost more than they save unless
comparisons are in fact very expensive compared to the cost of pointer
copying (and in Java comparison of unboxed types is cheap).  Indeed, for
native numeric types, where comparison is dirt cheap, quicksort generally
runs faster than mergesort despite that the former does _more_ comparisons
(because mergesort does so much more pointer-copying).

I had considered something "like this" for Python 2, but didn't pursue it
because comparison was defined between virtually any two types (34 < [1],
etc), and people were careless about that (both by design and by
accident).  In Python 3, comparison "blows up" for absurdly mixed types, so
specializing for homogeneously-typed lists is a more promising idea on the
face of it.

The comparisons needed to determine _whether_ a list's objects have a
common type is just len(list)-1 C-level pointer comparisons, and so goes
fast.  So I expect that, when it applies, this would speed even sorting an
already-ordered list with at least 2 elements.

For a mixed-type list with at least 2 elements, it will always be pure
loss.  But (a) I expect such lists are uncommon (and especially uncommon in
Python 3); and (b) a one-time scan doing C-level pointer comparisons until
finding a mismatched type is bound to be a relatively tiny cost compared to
the expense of all the "rich comparisons" that follow.

So +1 from me on pursuing this.

Elliot, please:

- Keep this on python-ideas.  python-dev is for current issues in Python
development, not for speculating about changes.

- Open an issue on the tracker:  https://bugs.python.org/

- At least browse the info for developers:
https://docs.python.org/devguide/

- Don't overlook Lib/test/sortperf.py.  As is, it should be a good test of
what your approach so far _doesn't_ help, since it sorts only lists of
floats (& I don't think you're special-casing them).  If the timing results
it reports aren't significantly hurt (and I expect they won't be), then add
specialization for floats too and gloat about the speedup :-)

- I expect tuples will also be worth specializing (complex sort keys are
often implemented as tuples).

Nice start! :-)
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Optimizing list.sort() by checking type in advance

2016-10-10 Thread Guido van Rossum
So maybe someone should explain to Elliott *why* his own benchmarks
are not trustworthy, rather than just repeat "use perf or timeit".
Actually, there are two things: (a) when something new comes along it
*always* needs to prove beyond a shadow of a doubt that it is actually
an improvement and not a timing artifact or a trick; (b) you can't
time sorting 10 values *once* and get a useful result. You have to do
it many times. And you have to make sure that creating a list of 10
random values isn't taken as part of your test -- that's tricky since
random() isn't all that fast; but it has to be done.

Although Elliott had it coming when he used needlessly offensive
language in his first post.

On Mon, Oct 10, 2016 at 5:09 PM, Steven D'Aprano  wrote:
> On Mon, Oct 10, 2016 at 09:16:32PM +, Elliot Gorokhovsky wrote:
>
>> Anyway, benchmarking technique aside, the point is that it it works well
>> for small lists (i.e. doesn't affect performance).
>
> You've been shown that there is something suspicious about your
> benchmarking technique, something that suggests that the timing results
> aren't trustworthy. Until you convince us that your timing results are
> reliable and trustworthy, you shouldn't be drawing *any* conclusions
> about your fastsort versus the standard sort.
>
>
> --
> Steve
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe: 
> https://mail.python.org/mailman/options/python-dev/guido%40python.org



-- 
--Guido van Rossum (python.org/~guido)
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Optimizing list.sort() by checking type in advance

2016-10-10 Thread Steven D'Aprano
On Mon, Oct 10, 2016 at 09:16:32PM +, Elliot Gorokhovsky wrote:

> Anyway, benchmarking technique aside, the point is that it it works well
> for small lists (i.e. doesn't affect performance).

You've been shown that there is something suspicious about your 
benchmarking technique, something that suggests that the timing results 
aren't trustworthy. Until you convince us that your timing results are 
reliable and trustworthy, you shouldn't be drawing *any* conclusions 
about your fastsort versus the standard sort.


-- 
Steve
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Optimizing list.sort() by checking type in advance

2016-10-10 Thread Nathaniel Smith
On Mon, Oct 10, 2016 at 2:16 PM, Elliot Gorokhovsky
 wrote:
> Hm... that is strange, but I don't think there's anything wrong with the way
> I'm timing, though I agree perf/timeit would be better. I ran the benchmark
> a couple of times and the numbers seem to exactly line up something like one
> in five times; perhaps not that crazy considering they're executing nearly
> the same code?

No, computer clocks are precise enough, and CPUs are wonky enough
(cache effects, etc.), that it should be effectively impossible to get
the same timing result twice in row, even for running exactly the same
code. I'm not sure what's going on, but it's weird. Making these kinds
of measurements is much more complicated than it looks and you really
need to use something like timeit or perf if you want trustworthy
results. Fortunately, they're easy to use :-)

-n

-- 
Nathaniel J. Smith -- https://vorpus.org
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Optimizing list.sort() by checking type in advance

2016-10-10 Thread Chris Angelico
On Tue, Oct 11, 2016 at 7:42 AM, Elliot Gorokhovsky
 wrote:
> ChrisA suggested I also try "make test" or something to get a more realistic
> benchmark. I will do that once I implement this as a patch, right now it's
> an extension module that subclasses list, so I can't just drop it into
> existing code without modification.

Oh, okay. If it's done that way, there's (in a way) a guarantee that
it won't worsen anything, because you have to explicitly request the
new behaviour. So if you KNOW that you're going to be doing a ton of
string-only sorting, you can call on this new list subclass, and if
you're not, you simply don't.

ChrisA
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Optimizing list.sort() by checking type in advance

2016-10-10 Thread Elliot Gorokhovsky
Hm... that is strange, but I don't think there's anything wrong with the
way I'm timing, though I agree perf/timeit would be better. I ran the
benchmark a couple of times and the numbers seem to exactly line up
something like one in five times; perhaps not that crazy considering
they're executing nearly the same code?

Anyway, benchmarking technique aside, the point is that it it works well
for small lists (i.e. doesn't affect performance).

On Mon, Oct 10, 2016 at 2:53 PM Nathaniel Smith  wrote:

> On Mon, Oct 10, 2016 at 1:42 PM, Elliot Gorokhovsky
>  wrote:
> > *** 10 strings ***
> > F.fastsort(): 1.6689300537109375e-06
> > F.sort(): 1.6689300537109375e-06
>
> I think something has gone wrong with your timing harness...
>
> For accurately timing microbenchmarks, you should use timeit, or
> better yet Victor Stinner's perf package:
>   https://perf.readthedocs.io/
>
> -n
>
> --
> Nathaniel J. Smith -- https://vorpus.org
>
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Optimizing list.sort() by checking type in advance

2016-10-10 Thread Nathaniel Smith
On Mon, Oct 10, 2016 at 1:42 PM, Elliot Gorokhovsky
 wrote:
> *** 10 strings ***
> F.fastsort(): 1.6689300537109375e-06
> F.sort(): 1.6689300537109375e-06

I think something has gone wrong with your timing harness...

For accurately timing microbenchmarks, you should use timeit, or
better yet Victor Stinner's perf package:
  https://perf.readthedocs.io/

-n

-- 
Nathaniel J. Smith -- https://vorpus.org
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Optimizing list.sort() by checking type in advance

2016-10-10 Thread Elliot Gorokhovsky
I'd like to reply to both questions with one email, if that's all right.

Bernardo Sulzbach asked, "How does this interfere with sorting very small
lists?", and ChrisA asked, "How much slower are sorts of heterogeneous
lists?". I modified the benchmark to answer both questions, the former at
the top, and the latter at the bottom (see the git repo):

*** 10 ints ***
F.fastsort(): 2.86102294921875e-06
F.sort(): 3.337860107421875e-06
*** 10 strings ***
F.fastsort(): 1.6689300537109375e-06
F.sort(): 1.6689300537109375e-06
*** 1e3 ints ***
F.fastsort(): 0.00013589859008789062
F.sort(): 0.00018906593322753906
*** 1e3 strings ***
F.fastsort(): 0.0002529621124267578
F.sort(): 0.0002772808074951172
*** 1e7 ints ***
F.fastsort(): 5.472854375839233
F.sort(): 7.8826072216033936
*** 1e7 strings ***
F.fastsort(): 10.104042053222656
F.sort(): 13.139304876327515
*** 1e7 ints + 1 float (to disable the optimization while keeping the
precheck)***
F.fastsort(): 7.57237982749939
F.sort(): 7.666172504425049

ChrisA suggested I also try "make test" or something to get a more
realistic benchmark. I will do that once I implement this as a patch, right
now it's an extension module that subclasses list, so I can't just drop it
into existing code without modification.

Let me know if you have any other questions/suggestions!

On Mon, Oct 10, 2016 at 12:18 AM Elliot Gorokhovsky <
elliot.gorokhov...@gmail.com> wrote:

> Hi,
>
> I posted here a while back asking what you guys thought about implementing
> radix sort for strings in list.sort(). You gave me a lot of reasons why
> that would be a bad idea. However, it got me thinking, and I came up with
> something that you may find interesting.
>
> First, some simple benchmark results (numbers are seconds, check out the
> extension module at https://github.com/embg/python-fast-listsort.git):
>
> *** 1e3 ints ***
> F.fastsort(): 0.00018930435180664062
> F.sort(): 0.0002830028533935547
> *** 1e3 strings ***
> F.fastsort(): 0.0003533363342285156
> F.sort(): 0.00044846534729003906
> *** 1e7 ints ***
> F.fastsort(): 5.479267358779907
> F.sort(): 8.063318014144897
> *** 1e7 strings ***
> F.fastsort(): 9.992833137512207
> F.sort(): 13.730914115905762
>
> The optimization uses the fact that, in practice, we are almost always
> sorting keys of the same type (note: not objects of the same type, *keys*
> of the same type; we could have a complex key function like str that takes
> many different types, but the keys are still all the same type). So we can
> just do one typecheck up front and then do unsafe comparisons during the
> sort (if our initial check passes). Specifically, we check that for all the
> PyObject* in saved_ob_item, the ob->ob_type are the same. Then we replace
> PyObject_RichCompare with ob_type->tp_richcompare. Additionally, we can
> check for the very common cases of ints and strings and give optimized
> comparison functions for those cases. It might not seem like this would
> save a lot of time, but it turns out that PyObject_RichCompare is a massive
> clusterf**k that has to test tons of type stuff before it can actually
> compare. Cutting that out ends up saving a *lot* of time, as the benchmark
> demonstrates.
>
> What do you think? I'm planning on writing this up into a patch, but
> wanted to get some feedback on the implementation and ideas for improvement
> first.
>
> Thanks,
> Elliot
>
>
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Optimizing list.sort() by checking type in advance

2016-10-10 Thread Chris Angelico
On Mon, Oct 10, 2016 at 5:18 PM, Elliot Gorokhovsky
 wrote:
> First, some simple benchmark results (numbers are seconds, check out the
> extension module at https://github.com/embg/python-fast-listsort.git):
>
> *** 1e3 ints ***
> F.fastsort(): 0.00018930435180664062
> F.sort(): 0.0002830028533935547
> *** 1e3 strings ***
> F.fastsort(): 0.0003533363342285156
> F.sort(): 0.00044846534729003906
> *** 1e7 ints ***
> F.fastsort(): 5.479267358779907
> F.sort(): 8.063318014144897
> *** 1e7 strings ***
> F.fastsort(): 9.992833137512207
> F.sort(): 13.730914115905762
>
> The optimization uses the fact that, in practice, we are almost always
> sorting keys of the same type

(Might be a topic for python-ideas rather than python-dev.)

Can you pick up a standard benchmark suite and use that instead of
these simplistic operations? How much slower are sorts of
heterogeneous lists - what's the impact/cost on those? If a large test
suite ("make test" if you don't have a nice benchmark handy - the
CPython test suite is a solid mass of code) shows an overall slowdown,
this probably isn't worth pursuing; if it shows a minor but
insignificant increase, there might be something worth looking into;
and if it shows a huge increase... well, to be honest, if it shows a
huge increase, I'd suspect a fault in the measurements, because
sorting isn't a significant part of most test suites :)

ChrisA
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] Optimizing list.sort() by checking type in advance

2016-10-10 Thread Bernardo Sulzbach

On 10/10/2016 03:18 AM, Elliot Gorokhovsky wrote:

Hi,

I posted here a while back asking what you guys thought about
implementing radix sort for strings in list.sort(). You gave me a lot of
reasons why that would be a bad idea. However, it got me thinking, and I
came up with something that you may find interesting.

First, some simple benchmark results (numbers are seconds, check out the
extension module at https://github.com/embg/python-fast-listsort.git):

*** 1e3 ints ***
F.fastsort(): 0.00018930435180664062
F.sort(): 0.0002830028533935547
*** 1e3 strings ***
F.fastsort(): 0.0003533363342285156
F.sort(): 0.00044846534729003906
*** 1e7 ints ***
F.fastsort(): 5.479267358779907
F.sort(): 8.063318014144897
*** 1e7 strings ***
F.fastsort(): 9.992833137512207
F.sort(): 13.730914115905762



The numbers are good. How does this interfere with sorting very small 
lists? Obviously, even if it does not help with very small lists, we can 
always put a threshold on the size and take this path or not.


--
Bernardo Sulzbach
http://www.mafagafogigante.org/
mafagafogiga...@mafagafogigante.org
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com