Skip to content

Faster parallel array partition and choose - #1423

Merged
KevinRansom merged 8 commits into
dotnet:masterfrom
jackmott:faster-parallel-partition
Aug 23, 2016
Merged

Faster parallel array partition and choose#1423
KevinRansom merged 8 commits into
dotnet:masterfrom
jackmott:faster-parallel-partition

Conversation

@jackmott

@jackmottjackmott commented Aug 12, 2016

Copy link
Copy Markdown
Contributor

Runtime is about 1.3x faster on my machine (4 core i7 mobile), with no memory use penalty. Would love input on this one, there may be some ways to improve on the approach. I am deep in uncharted Parallel.For territory.

BenchmarkDotNet results, partitioning a random int array with (fun x -> x % 2 = 0)

Note that the benchmark results are somewhat stochastic, they will bounce around from 35% to 10% better each time I run the suite, there doesn't appear to be a general trend where it gets better or worse moving from 1 million to 10 million. I've also used more complex predicates and the relative differences are similar.

Host Process Environment Information:
BenchmarkDotNet=v0.9.8.0
OS=Microsoft Windows NT 6.2.9200.0
Processor=Intel(R) Core(TM) i7-4712HQ CPU 2.30GHz, ProcessorCount=8
Frequency=2240907 ticks, Resolution=446.2479 ns, Timer=TSC
CLR=MS.NET 4.0.30319.42000, Arch=64-bit RELEASE [RyuJIT]
GC=Concurrent Workstation
JitModules=clrjit-v4.6.1590.0
Type=SIMDBenchmark Mode=Throughput Platform=X64 Jit=RyuJit GarbageCollection=Concurrent Workstation 

Partition

MethodLengthMedianStdDevScaledGen 0Gen 1Gen 2Bytes Allocated/Op
Original100021.8514 us0.5300 us1.000.16--3,471.77
New100020.5297 us0.8840 us0.940.17--3,489.75
Original10000160.0466 us3.1249 us1.001.21--28,955.03
New10000118.1885 us2.8572 us0.741.20--28,666.02
Original1000001,282.9827 us7.3705 us1.00--10.17211,334.08
New100000917.0063 us17.4501 us0.71--7.27151,441.53
Original100000012,467.9427 us728.8799 us1.00--65.992,353,833.73
New10000009,700.7108 us990.4339 us0.78--65.242,309,151.64
Scalar100000013,680.7468 us212.0151 us1.103.25-37.574,361,586.45
Original10000000125,043.1745 us1,753.3497 us1.00--35.2829,670,713.02
New1000000086,908.7271 us1,472.4448 us0.70--35.5329,909,345.33

Choose

MethodLengthMedianStdDevScaledGen 0Gen 1Gen 2Bytes Allocated/Op
Original100024.1173 us1.8355 us1.000.52--13,721.83
New100025.8602 us0.3443 us1.070.47--12,292.06
Original10000235.2287 us4.9615 us1.004.55--157,065.29
New10000190.6397 us5.1752 us0.814.72--167,680.01
Original1000002,352.3452 us58.5964 us1.0018.99-10.231,206,016.17
New1000001,696.8924 us38.6374 us0.7218.30-9.541,093,127.52
Original100000023,316.6749 us899.0359 us1.00269.101.6241.2914,659,078.49
New100000015,062.9299 us1,155.5808 us0.65294.001.3946.0515,348,631.44
Original10000000178,700.9122 us24,916.3155 us1.002,524.00-38.00142,952,816.14
New10000000163,852.8507 us17,740.5511 us0.922,634.24-35.28141,815,184.40

@msftclas

Copy link
Copy Markdown

Hi @jackmott, I'm your friendly neighborhood Microsoft Pull Request Bot (You can call me MSBOT). Thanks for your contribution!
You've already signed the contribution license agreement. Thanks!

The agreement was validated by Microsoft and real humans are currently evaluating your PR.

TTYL, MSBOT;

@jackmott

jackmott commented Aug 12, 2016

Copy link
Copy Markdown
ContributorAuthor

Whats does this mean, from the QA tests. Something about assembly version being wrong, what would cause that?
"Conformance\DeclarationElements\CustomAttributes\AttributeUsage (AssemblyVersion03.fs) -- failed"

@forki

Copy link
Copy Markdown
Contributor

Probably unrelated

@jackmott

Copy link
Copy Markdown
ContributorAuthor

Going to probably pull in the same trick for Parallel.choose in a minute.

@jackmottjackmott changed the title [WIP] Faster parallel array partitionFaster parallel array partition and chooseAug 12, 2016
@ReedCopsey

Copy link
Copy Markdown
Contributor

Note that using Parallel.For can have bad repercussions in a situation where the algorithm is being used in a threaded context. If this is called on a thread while the other threads are already saturated via CPU usage, best case, it'd be the same as doing it in serial, and worst (and more likely) case, significantly slower.

I'd be very careful about using Parallel loops within core library functions, since you can't control where they're going to be used, and this could be disastrous when used in highly threaded code. It's also unexpected - you'd expect to be safe using core library functions when threading at a "higher level" in your application, and this would make that assumption invalid.

@jackmott

jackmott commented Aug 12, 2016

Copy link
Copy Markdown
ContributorAuthor

It was a Parallel.For originally, I just pulled the accumulation into it, rather than iterating over the array again to count it up afterwards.

Also this is in a separate sub module - Array.Parallel, which was already in place, so chance of accidental improper usage is low.

I agree with your points completely though, and was thinking of blogging about that very issue!

@cartermp

Copy link
Copy Markdown
Contributor

@jackmott This is fantastic, as with your other PRs thus far. 👍

Could you also add your test script to this PR and further PRs? @smoothdeveloper and I were chatting, and he had mentioned that it would be great to have the perf test scripts for these changes in the repo so we can use them as a baseline for further improvements.

The location for this would be in tests/scripts/{some-folder-name-which-makes-sense}.

Thanks!

@jackmott

Copy link
Copy Markdown
ContributorAuthor

@cartermp do you mean a script to test that performance has not regressed? Or for correctness? The former, I'm not sure how to do, since the old function wouldn't exist any more. The latter I assume already exists, since I haven't added a new function. Happy to help, need guidance. Thanks!

@KevinRansom

Copy link
Copy Markdown
Contributor

Not a test case, more an indication of how the numbers were gathered.

It gives other developers an idea about how to go about testing their performance improvements.

Kevin

From: Jack Mott [mailto:notifications@github.com]
Sent: Friday, August 12, 2016 1:54 PM
To: Microsoft/visualfsharp visualfsharp@noreply.github.com
Subject: Re: [Microsoft/visualfsharp] Faster parallel array partition and choose (#1423)

@cartermphttps://github.com/cartermp do you mean a script to test that performance has not regressed? Or for correctness? The former, I'm not sure how to do, since the old function wouldn't exist any more. The latter I assume already exists, since I haven't added a new function. Happy to help, need guidance. Thanks!


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHubhttps://github.com//pull/1423#issuecomment-239557184, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AE76FqMB2ilp5Rnv74NQ5qGXi2MFhG0Rks5qfN19gaJpZM4Jisxr.

@jackmott

Copy link
Copy Markdown
ContributorAuthor

Gotcha. Would it be ok to pull BenchmarkDotNet into the solution? Are there other perf tests scripts I can use as a guide?

@ReedCopsey

Copy link
Copy Markdown
Contributor

@jackmott Oh, great - sorry - just saw "for Array.choose" and wasn't thinking this was for Array.Parallel. Sorry about that! This is a great improvement - using the accumulators is definitely better.

@cartermp

Copy link
Copy Markdown
Contributor

@jackmott I'd be fine with a package reference. I think it would be best if the .dll for it wasn't checked in, though. As for examples, it looks like all we have is Compiler Perf Scripts. Not too much to go off of, so I think it's safe to say that you could do whatever you feel is reasonable and it'll be fine.

Biggest thing is just to ensure that anyone can clone the repo and begin running the scripts to see performance results themselves. I'm also happy to iterate here and just get some scripts checked in while we figure out a good solution.

@jackmott

Copy link
Copy Markdown
ContributorAuthor

Ok I will give it a go

@KevinRansom

Copy link
Copy Markdown
Contributor

Given that the tests will run on different hardware, and that there is a before and after component. Seeing the results is less interesting than seeing the methodology. And the ability to examine the test code to look for where it may impzact the result demonstrated.

Kevin

From: Phillip Carter [mailto:notifications@github.com]
Sent: Friday, August 12, 2016 2:44 PM
To: Microsoft/visualfsharp visualfsharp@noreply.github.com
Cc: Kevin Ransom Kevin.Ransom@microsoft.com; Comment comment@noreply.github.com
Subject: Re: [Microsoft/visualfsharp] Faster parallel array partition and choose (#1423)

@jackmotthttps://github.com/jackmott I'd be fine with a package reference. I think it would be best if the .dll for it wasn't checked in, though. As for examples, it looks like all we have is Compiler Perf Scriptshttps://github.com/Microsoft/visualfsharp/tree/master/tests/scripts. Not too much to go off of, so I think it's safe to say that you could do whatever you feel is reasonable and it'll be fine.

Biggest thing is just to ensure that anyone can clone the repo and begin running the scripts to see performance results themselves. I'm also happy to iterate here and just get some scripts checked in while we figure out a good solution.


You are receiving this because you commented.
Reply to this email directly, view it on GitHubhttps://github.com//pull/1423#issuecomment-239567197, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AE76Fogf49IRykHqGp_rD9nUCCznM-nWks5qfOklgaJpZM4Jisxr.

@jackmott

Copy link
Copy Markdown
ContributorAuthor

Sample perf test script added. Let me know if I should rename/relocate/revise.
It is not formatted as an fsx, because I never use the REPL so am not familiar with it, but I could learn!

@jackmott

Copy link
Copy Markdown
ContributorAuthor

It would be neat if you had coverage of any perf relevant functions, and maybe weekly, check today's master against 1 week ago, report any that have regressed by some % for review. Massively time consuming test, couldn't do it on every PR/commit I don't think.

@KevinRansom

Copy link
Copy Markdown
Contributor

@dotnet-bot test this please

@KevinRansom

KevinRansom commented Aug 13, 2016

Copy link
Copy Markdown
Contributor

Appveyor Failure is due to appveyor timeout, it will be fixed by: #1425

@KevinRansom

Copy link
Copy Markdown
Contributor

@dotnet-bot test this please

@veikkoeeva

Copy link
Copy Markdown

It would be neat if you had coverage of any perf relevant functions, and maybe weekly, check today's master against 1 week ago, report any that have regressed by some % for review.

@jackmott In that case dotnet/BenchmarkDotNet#155 looks like very promising.

@KevinRansom

Copy link
Copy Markdown
Contributor

@jackmott If benchmark.net is a nuget package, then adding it will be great.

@jackmott

Copy link
Copy Markdown
ContributorAuthor

@KevinRansom it is, but it pulls down a large set of dependencies I believe. Would you want it added to one of the existing projects? Create a new project with it inside the scripts folder?


[<Benchmark>]
member self.New () =
array |> partition (fun x -> x % 2 = 0)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might be mistaken, but shouldn't this be partitionNew ?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep!

@KevinRansom

Copy link
Copy Markdown
Contributor

Just add it to packages.config. It’s a one time cost and I’m guessing it’s less than the cost of pulling down the enormous set of dependencies we currently pull. I appreciate that optimizers may grumble … but the payback of a standardized way of reproducing and reporting performance issues is going to be tremendous. Your performance PR’s are already much easier to approve than others because of it. So I’m all for adding it.

Kevin
From: Jack Mott [mailto:notifications@github.com]
Sent: Monday, August 15, 2016 10:55 AM
To: Microsoft/visualfsharp visualfsharp@noreply.github.com
Cc: Kevin Ransom Kevin.Ransom@microsoft.com; Mention mention@noreply.github.com
Subject: Re: [Microsoft/visualfsharp] Faster parallel array partition and choose (#1423)

@KevinRansomhttps://github.com/KevinRansom it is, but it pulls down a large set of dependencies I believe. Would you want it added to one of the existing projects? Create a new project with it inside the scripts folder?


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHubhttps://github.com//pull/1423#issuecomment-239875660, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AE76FolXzl296zz8xS1DizSD_zOV8jmSks5qgKfkgaJpZM4Jisxr.

@jackmott

Copy link
Copy Markdown
ContributorAuthor

All set here, benchmarkdotnet added to packges.config

@KevinRansom

Copy link
Copy Markdown
Contributor

Looks great, thanks for this work

Kevin

@jackmott

Copy link
Copy Markdown
ContributorAuthor

Anything else needed here? I think it is all ready.

@KevinRansom
KevinRansom merged commit 4873e4c into dotnet:masterAug 23, 2016
@KevinRansom

Copy link
Copy Markdown
Contributor

@jackmott
Thank you for this work

Kevin

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants

@jackmott@msftclas@forki@ReedCopsey@cartermp@KevinRansom@veikkoeeva@rojepp