BeforeIT.jl - High-Performance Agent-Based Macroeconomics in Julia

Hi all,

I’d like to announce BeforeIT.jl, a Julia package for macroeconomic agent based modelling based on a recent and very well known model. The package is particularly performant in respect to other implementations with which we have benchmarked it, we have in the ArXiv preprint describing the package this sweet figure which I think it will be very appealing for Julia people:

To be frank though, a key part of these performance gains comes from the use of better algorithms, but even without them, the package was already at C-level speed — which we found pretty remarkable! What’s maybe even more impressive is that it manages to compete with a High Performance Computing implementation while relying only on basic multithreading.

BeforeIT.jl is designed to be highly flexible and adaptable: it can, in principle, be calibrated
to any country for forecasting and policy analysis. Its modular architecture also makes it easy to extend in multiple directions to suit different research needs. While this is the most complex model we’ve built so far, we’re aiming to create an ecosystem of models to support experimental design and proof-of-concept work. If you’re interested, check out ABCredit.jl and Mark0.jl as well.

We look forward to hear any feedback you’d like to share about it!

15 Likes

Congrats on the package and preprint!
I’d be thrilled to work with you on integrating automatic differentiation to BeforeIT.jl. My current lab uses another multi-agent simulator (MATSim) whose calibration is very costly, and I am curious to see whether autodiff can provide a new way to estimate parameters for such models. Your work would be an ideal starting point because it’s all in Julia :wink:
Of course there are non-differentiable and randomized operations inside the simulator, but we have ways around those (it was actually the topic of my PhD). Feel free to reach out if you’re interested in collaborating!

5 Likes

Great! It comes as no surprise that you are able to compete with C-based programs :wink:

I recall the american federal reserve was using Julia? Worth mentioning as well with the other citations! But I don’t remember now where I’ve heard it.

I saw that your parallelization is using threading, like Agents.jl, but the way we both do it is apparently deprecated. See e.g., Likely erroneous use of `Threads.nthreads` and `Threads.threadid` · Issue #167 · JuliaDynamics/TimeseriesSurrogates.jl · GitHub

Perhaps it is worth highlighting this in the julia package comparisons website: Agent Based Modelling . I am curious and would have loved to see some comparison with Agents.jl, but Agents.jl is not even mentioned or cited in the paper, even though the packages have so similar interfaces that the functions are named the same, such as run! or ensemblerun. Is there any chance you can provide some info? Such as different design choices, different capabilities, etc.? I know for example Vanaha.jl has a fundamentally different design with respect to both time stepping (synchronous) and spatial neighborhoods.

5 Likes

I recall the american federal reserve was using Julia? Worth mentioning as well with the other citations! But I don’t remember now where I’ve heard it.

This rang a bell! I saw it on Julia’s wikipedia page, and the citation there links to this GitHub repo.

Also congrats @Tortar on the really cool package! :slight_smile:

5 Likes

Hi @gdalle thanks for your interest! (I am another one of the original authors of BeforeIT.jl).
Given the underlying model, automatic differentiation on BeforeIT would be a game changer for the entire field of economic ABMs, and would certainly be widely used. The difficult bit to change is probably the “search and matching” function, but that part can be simplified using a trick recently proposed by the University of Oxford. Let’s talk about it

4 Likes

Yes, not citing Agents.jl was a mistake, some of our interface was inspired by the one of Agents.jl as you noticed and we will make sure that in the next version of the preprint or in the paper we would like to publish it will be mentioned. On the comparison part I’m less sure, BeforeIT.jl is a more specialized package for macroeconomics ABMs, we still need to improve its extensibility and other things to be more robust as a framework on its own. I’d actually love to have Agents.jl be the back-end of it and that is also why we already have some similar functions as a first step, but the refactor is somewhat hard because BeforeIT.jl wasn’t initially coded with this is mind and also because it is built upon a different structure for agents, they are represented as Struct-of-Arrays instead of Array-of-Structs, and the SoA design could still be better performance wise for this kind of models. Maybe we could start backwards, by tracking in an issue the ability to use the SoA pattern for agents in Agents.jl.

Thanks for the pointer, I recall that we indeed had that problem in a past release, but then I eventually fixed it, we only use nthreads to split the work which should be safe as far as I can tell.

3 Likes

Hm, this doesn’t sound like complete blocker though. You can still extend the AgentBasedModel interface from Agents.jl. After our extensive v6 refactor, the internals of the model do not matter. Or, they shouldn’t :wink:

As long as you can define a sensible function for add_agent_to_model! and model[id], wouldn’t it be possible for the API to be implemented still? This way you could be using GridSpace or better yet OSMSpace for free! Because the whole AbstractSpace functionality truly doesn’t care about how the agents are stored, since all spaces store a copy of the agent IDs anyway. So I would imagine an extension being making a new AgentBasedModel subtype that is like a BeforeITABM that has a lot of the specific containers for the banks, rest of the world, etc., and also has the arbitrary .parameters container for auxilary stuff. This is something we should definitely discuss when you guys give a talk in the JuliaDynamics meeting next month.

What would be a true blocker is having a 100% synchronous design: yes, this wouldn’t work with the current AbstractSpace design of agents as all move_agent! functions have a sequential design.

3 Likes

mmmh, actually yes! It makes sense, this is actually why we did all that back and forth on model design in any case as you say :laughing:

Will try and report back. In the meantime I have opened an issue about a possible Optional Struct-of-Arrays layout for agents · Issue #1146 · JuliaDynamics/Agents.jl · GitHub because seems sensible to support that in general to me. Maybe if my exploration succeed we could then move some of it to Agents.jl itself and close the issue.

3 Likes

Hi @AldoGl This direction was already raised here [Improve speed of simulations by Tortar · Pull Request #18 · bancaditalia/BeforeIT.jl · GitHub] to no avail. Agents.jl and JuliaDynamics are really the best that you can join. @Datseris :slightly_smiling_face:

1 Like

We have started a discussion about making Agents.jl a backend for BeforeIT.jl here: Optional Struct-of-Arrays layout for agents · Issue #1146 · JuliaDynamics/Agents.jl · GitHub . There appears to be no meaningful barriers to making this happen, and in fact I believe that this would be only a 100-200 lines of code pull request in Agents.jl that would implement one more model type that uses structs of arrays.

The better question is whether there is a benefit to have structs of arrays at all, but this is not as trivial to answer!