Mike makes an excellent point here – prior to his email, no one proposed
any different versions of the Mathematica computation, and this one is
slower than the original. On the other hand, there were a dozen rather
different approaches in Julia, with various speeds, but all pretty decent
and some very fast. It's not a virtue of the language that there are so
many ways to express this problem – that's inherent to the problem. What
Julia is providing, in my view, is the freedom to explore the space of
solutions with a lot of options, all with pretty decent performance and
some with excellent performance. In Mathematica, you hope that the built-in
algorithm is good enough – and often it is, because their standard library
is really quite amazing – but sometimes it's not and you really need that
additional 10x speed increase that you could get with a custom algorithm
and a fast language. That, I believe, was Jason's point about trying to
write factors yourself – you're supposed to be able to write things like
that pretty easily. Our factor function is pretty
simple<https://github.com/JuliaLang/julia/blob/859b9e5f1ee4615be86c566489d3699f51f5ed09/base/primes.jl#L74-L115>and
literally has a comment above it indicating that we probably want to
find a faster factorization algorithm.


On Mon, Mar 17, 2014 at 6:05 AM, Mike Innes <[email protected]> wrote:

> Ok, so to clear things up here, you could in principle port the
> Mathematica solution to Julia, and it would very likely be faster.
>
> divsum(n) = DivisorSigma(1, n) - n
> isamicable(n::Integer) = divsum(n) != n && divsum(divsum(n)) == n
> @time sum(filter(isamicable, 1:9999))
>
> The only problem is that we don't have a carefully optimised DivisorSigma
> function in the standard library. That's it; there's no magic going on
> here, in Julia or Mathematica. But what you're comparing is not Julia and
> Mathematica, it's a naive algorithm in Julia vs. a different algorithm in
> C. Now, fair enough, this perhaps says something about Mathematica's
> impressive standard library compared to Julia's, but it really doesn't make
> any sense as a performance comparison.
>
> If you only ever need to rely on built-in functions and write a few lines
> of code for yourself, Mathematica is great. But Julia's real benefit comes
> when the standard library lets you down. You can simulate this, as Jason
> points out, by forgetting that DivisorSigma[] exists; so let's try solving
> the problem again, with the same algorithm you used in Julia originally in
> both languages:
>
> divsum(n) = sum(map(x-> n%x == 0, 1:n-1))
> isamicable(n::Integer) = divsum(n) != n && divsum(divsum(n)) == n
> @time sum(filter(isamicable, 2:9999))
>
> DivSum[n_] := Total[Select[Range[n - 1], Mod[n, #] == 0 &]]
> AmicableQ[n_Integer] := DivSum[n] != n && DivSum[DivSum[n]] == n
> Plus @@ Select[Range[9999], AmicableQ] // Timing
>
> The Julia above takes 18 seconds on my system, whereas the Mathematica
> takes 160 seconds. Mathematica is slow when you step outside the standard
> library.
>
> On the other hand, as others have shown, a really fast implementation was
> achievable in Julia despite the fact that it wasn't built in - that's what
> you should take away from this.
>

Reply via email to