ChrisRackauckas

Joined 10 years ago

Karma
3,832
Submissions
933
Member since
Oct 6
I am the developer of the SciML Scientific Machine Learning Open Source Software Organization (https://sciml.ai/), an organization for Julia, Python and R packages for integrated, composible, and fast scientific machine learning. I also have used quite a bit of MATLAB, C, and Fortran (well, at least used for numerical work), but these days. I think the purpose of discussing technical topics is the dissemination of ideas, so let's bring each other up not down!
View on Hacker News

Recent submissions

Comment · 18 days ago
The book referred to was released in 2022, around the same month as Symbolics.jl, so it wouldn't have existed when the author was writing it.
Comment · 18 days ago
Comment · 1 month ago
They are green too, which means they were just made today. That's a pretty nice HN feature! It shows that there's literally 5 adversarial green sock puppet accounts that were made just to comment in this thread, so almost certainly one person with a grudge who is afraid to make a non-anonymous argument on the merits.
Comment · 8 months ago
Are you using Polyester.jl? Large numbers of threads are not optimized with Base threads usage due to GC interactions + the hierarchical threading adds overhead vs "unsafe" thread techniques which don't support the worksharing. Polyester is thus required to get very low overhead threading matching performance of non-worksharing scenarios.
Comment · 11 months ago
The caveat to mention here is that this is with the standard IO interface. If you use Core.println instead of println you get something substantially smaller. A limitation of v1.12 is that the handling of IO is not that great, and this is something that IIUC is being addressed in the v1.13 updates.
Comment · 1 year ago
No it only uses the same LLVM compiler passes and you enable certain optimizations locally via macros if you want to allow reordering in a given expression.
Comment · 1 year ago
v1.13 already has a good number of improvements to trim in the cases which are less analyzable, but even then I think the best thing for the package ecosystem is to start to become really good for trim, JETLS, etc. through statically checking things.
Comment · 1 year ago
We use it for binary deployments via building simulations into the FMI standard (i.e. building FMUs) https://fmi-standard.org/. We still need to get libraries updated for getting the smallest possible trim when using the more computationally difficult implicit methods, but at least the stack is matured for simple methods like explicit RK and Rosenbrock-type solvers already. For folks interested in --trim on SciML, the PR to watch is https://github.com/SciML/NonlinearSolve.jl/pull/665 which is currently held up by https://github.com/SciML/SciMLBase.jl/pull/1074 which is the last remaining nugget to get the vast majority of the SciML solver set trimming well. So hopefully very soon for anyone interested in this part of the world. Note that does not include inverse problems in the binary as part of small trim.

But all of this is more about maturing the ecosystem to be more amenable to static compilation and analysis. The whole SciML stack had an initiative starting at the beginning of this summer to add JET.jl testing for type inference everywhere and enforcing this to pass as part of standard unit tests, and using AllocCheck.jl for static allocation-free testing of inner solver loops. With this we have been growing the surface of tools that have static and real-time guarantees. Not done yet, some had to be marked as `@test_broken` for having some branch that can allocate if condition number hits a numerical fallback and such, but generally it's getting locked down. Think of it as "prototype in Julia, deploy in Rust", except instead of re-writing into Rust we're just locking down the behavior with incrementally enforcing the package internals to satisfy more and more static guarantees.

Comment · 1 year ago
Julia v1.12, the unreleased version which is currently in release candidate stage (and has had a longer RC stage than expected but should be done at least by the end of the year) has the ability to fully ahead of time compile and generate binaries, like you would expect from a language like C. It also trims these binaries so that they are a reasonable size given the elements of the runtime that are used. Thus for good type-stable code you get callable binaries without JIT overhead, and this leads to a much better CLI experience. It will take a bit of time so that there's more package tooling and support built around this feature, but this is the path a lot of the ecosystem CLI tooling is now going and that will be a pretty dramatic shift in the usability for these kinds of use cases which Julia had traditionally ignored.
Comment · 1 year ago
This has nothing to do with floating point error accumulation or numerical stability in the floating point sense. You can do this with arbitrary sized floating point values and you will still get the same non-convergence result.
Comment · 1 year ago
This tool already exists in Python and R. See https://cran.r-project.org/web/packages/diffeqr/index.html and https://anaconda.org/conda-forge/diffeqpy. Julia has language bindings that make it simple enough to bind to other high level languages that these projects are maintained by the core team and supports lots of the library, including forms of automatic differentiation and GPU kernel generation. See for example the bindings that allow for usage within PyTorch https://github.com/SciML/juliatorch and the Python-based Collab notebooks showing the GPU usage https://colab.research.google.com/drive/1bnQMdNvg0AL-LyPcXBi....

With Julia v1.12's small binary generation, we plan to release forms via binaries with C ABIs over the next year as well.

Are those sufficient or should we consider supporting other deployments?

Comment · 1 year ago
Interesting to see this here! This example is one of the ones mentioned in the appendix of https://arxiv.org/abs/2406.09699, specifically "4.1.2.4 When AD is algorithmically correct but numerically wrong".

If people want a tl;dr, the main idea is you can construct an ODE where the forward pass is trivial, i.e. the ODE solution going forwards is exact, but its derivative is "hard". An easy way to do this is to make it so you have for example `x' = x - y, y' = y - x`, with initial conditions x(0)=y(0). If you start with things being the same value, then the solution to the ODE is constant since `x' = y' = 0`. But the derivative of the ODE solution with respect to its initial condition is very non-zero: a small change away from equality and boom the solution explodes. You write out the expression for dy(t)/dy(0) and what you get is a non-trivial ODE that has to be solved.

What happens in this case though is that automatic differentiation "runs the same code as the primal case". I.e., automatic differentiation has the property that it walks through your code and differentiates the steps of your code, and so the control flow always matches the control flow of the non-differentiated code, slapping the derivative parts on each step. But here the primal case is trivial, so the ODE solver goes "this is easy, let's make dt as big as possible and step through this easily". But this means that `dt` is not error controlled in the derivative (the derivative, being a non-trivial ODE, needs to have a smaller dt and take small steps in order to get an accurate answer), so the derivative then gets error due to this large dt (or small number of steps). Via this construction you can make automatic differentiation give as much error as you want just by tweaking the parameters around.

Thus by this construction, automatic differentiation has no bound to the error it can give, and no this isn't floating point errors this is strictly building a function that does not converge to the correct derivative. It just goes to show that automatic differentiation of a function that computes a nice error controlled answer does not necessarily give a derivative that also has any sense of error control, that is a property that has to be proved and is not true in general. This of course is a bit of a contrived example to show the point that the error is unbounded, but then it points to real issues that can show up in user code (in fact, this example was found because a user opened an issue with a related model).

Then one thing that's noted in here too is that the Julia differential equation solvers hook into the AD system to explicitly "not do forward-mode AD correctly", incorporating the derivative terms into the time stepping adaptivity calculation, so that it is error controlled. The property that you get is that for these solvers you get more steps to the ODE when running it in AD mode than outside of AD mode, and that is a requirement if you want to ensure that the user's tolerance is respected. But that's explicitly "not correct" in terms of what forward-mode AD is, so calling forward-mode AD on the solver doesn't quite do forward mode AD of the solver's code "correctly" in order to give a more precise solution. That of course is a choice, you could instead choose to follow standard AD rules in such a code. The trade-off is between accuracy and complexity.

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton