tinygo icon indicating copy to clipboard operation
tinygo copied to clipboard

Multicore support

Open aykevl opened this issue 4 years ago • 11 comments

We need to support multi core systems some day:

  • Some microcontrollers have more than one core that we'd like to use (RP2040, ESP32)
  • Most operating systems have multiple cores.

At the same time, support for multi core shouldn't (significantly) regress single-core performance on microcontrollers, because almost all microcontrollers are single core.

To support multi core, there need to be changes to:

  • the scheduler, to schedule over more than one core
  • channels (implemented in the runtime)
  • the garbage collector (it needs to stop all goroutines to scan their stacks)
  • wrappers for atomic instructions (see #2307)
  • packages like sync
  • ... probably more

I propose we add a new unicore (or singlecore, singlethread, ...) build tag for single core chips and schedulers, so that we can know at build time whether a configuration can assume it's only running in a single (hardware) thread and optimize accordingly.

I suspect it's easiest to not add multi core support first to a chip (RP2040, ESP32) but to an operating system. Operating system threads are already well defined and require the vast majority of changes that are also required for multi core support on a chip (see the list above). I propose we add a -scheduler=threads for that, where each goroutine is running in a separate OS thread. This is much simpler to implement than Go runtime style green threads because it doesn't require special handling of blocking system calls.

aykevl avatar Dec 30 '21 12:12 aykevl

Guess we can update the Non-Goals of the readme.md now image

Nerzal avatar Dec 30 '21 12:12 Nerzal

Perhaps target a FreeRTOS or similar to start?

EDIT: I now see you mentioned you would rather start with an OS, and did not actually imply that it would be on a RTOS.

eyz avatar Dec 30 '21 16:12 eyz

Guess we can update the Non-Goals of the readme.md now

Yes, feel free to send a PR :)

Perhaps target a FreeRTOS or similar to start?

No, that would be far more difficult. We already have a RTOS-like scheduler, adding FreeRTOS or similar would make things quite complicated. And add an external dependency that I'd really like to avoid.

aykevl avatar Dec 30 '21 16:12 aykevl

Hi all, any updates on this?

Although I haven't worked much with embedded systems I would like to lend a hand to add support for this.

migueleliasweb avatar Aug 14 '22 02:08 migueleliasweb

I am curious if any progress has been made for supporting multiple cores? Did not find any hack or PR about it. Should we consider this is not a primary goal for TinyGo? Thank you!

couillonnade avatar Apr 27 '23 02:04 couillonnade

There hasn't been any development on this feature.

Should we consider this is not a primary goal for TinyGo?

It is not, because only very few microcontrollers have multiple cores (the rp2040 and esp32 are the only two I know of).

aykevl avatar Apr 27 '23 02:04 aykevl

Thank you for the feedback @aykevl. I'm mainly targeting RP2040 that has more power than many other MCU for a fraction of the price.

couillonnade avatar Apr 27 '23 03:04 couillonnade

is this still a goal? or is it gone?. just as said this will really benefit the rp2040's architecture.

improvisor40 avatar May 28 '23 23:05 improvisor40

is this still a goal? or is it gone?.

Yes, eventually, but other things have been of higher priority so far.

aykevl avatar May 31 '23 16:05 aykevl

Was wondering if there was a middle ground here? What would it look like if there was support like what Arduino's stack does? Letting us fire up the other core as an independent entity.

kingsquirrel152 avatar Aug 15 '24 17:08 kingsquirrel152

I've actually been investigating this. Spent a few days trying to get channels to work but it's quite difficult. I've paused it for now because Go 1.23 support (and the coming release) is more important right now.

The first step for parallelism will be to add a new "scheduler" that just puts every goroutine on a separate OS thread in Linux. Why not on a MCU? Because 90% or so of the work is shared between Linux and MCU multicore support, and it's much easier to debug stuff on Linux.

aykevl avatar Aug 15 '24 18:08 aykevl

Update: continued work on this feature (see https://github.com/tinygo-org/tinygo/pull/4549 for example). I've written a parallelism-aware channel implementation and it works for ./testdata/channel.go. That's probably one of the harder parts of parallelism support and it works 🎉 I'll continue work on other parts like the sync package and the GC.

aykevl avatar Oct 25 '24 17:10 aykevl

And now a work-in-progress PR: https://github.com/tinygo-org/tinygo/pull/4559

aykevl avatar Oct 28 '24 15:10 aykevl

Thanks @aykevl for working on this!

I have a question about the easiest possible workaround that involves minimum effort to utilise two of the pico's cores. Do you think is possible a "fork"-like style where the same app is deployed on both cores and TinyGo gives hint to the app in which core it runs and from there it can run independently, i.e. not moving goroutines over different cores. Ideally they should use concurrently the network (to talk with one another) or using channels.

ylishev avatar Feb 09 '25 20:02 ylishev

I’m excited to notice the talk on multi core On the RP2040 at Fosdem https://fosdem.org/2025/schedule/event/fosdem-2025-5736-implementing-parallelism-how-we-added-threading-and-multicore-support-in-tinygo/

How do I get my hands on it to test?

gherlein avatar Mar 23 '25 21:03 gherlein

I have some very hacky code here, that I used at FOSDEM: https://github.com/tinygo-org/tinygo/compare/3767decf9e272cd34ab3b7c4807758df33af11a5...threading-rp2040-2 I was in a rush to get a demo working, and it was working at the time (you can see it in the talk!) but for some reason I can't get it to fully work right now on my Gopher Badge. Anyway, that's the code I've used, it might be interesting to look at. It'll need some very heavy cleaning up before it can be submitted as a PR.

aykevl avatar Apr 01 '25 07:04 aykevl

I checked out that branch and built it. But trying to compile a simple test results in this:

/home/gherlein/src/tinygo-stuff/tinygo/src/runtime/runtime_rp2040.go:172:2: undefined: runSecondary

io:~/src/tinygo-stuff/tinygo> git branch release

  • threading-rp2040-2

I'm trying to understand why it's not found even though it plainly there in scheduler_cores.go.

Any hints? Am I missing some flag somehow?

gherlein avatar Apr 07 '25 15:04 gherlein

You also need -scheduler=cores, the default is still -scheduler=tasks (which got broken). Note that this branch has a few bugs I found when I continued work on this. But before I make a new PR, I think I'll want to refactor the scheduler code a bit so the changes are easier to integrate.

aykevl avatar Apr 09 '25 13:04 aykevl

Is this happening yet? There's an article https://www.hackster.io/news/tinygo-goes-multi-core-on-the-raspberry-pi-rp2040-eebdcc0e55ee that says yes, but his code example is wrong so I'm wondering...

gherlein avatar Sep 13 '25 13:09 gherlein

Yes its happening, but with the latest version of tinygo

improvisor40 avatar Sep 13 '25 13:09 improvisor40

Can you point me at any kind of documentation please? Do I still need -scheduler=cores

Are there examples I can draw from?


Greg Herlein | +1-415-368-7546 | LinkedIn http://www.linkedin.com/in/gherlein | KO6HAX

On Sat, Sep 13, 2025 at 6:21 AM improvisor40 @.***> wrote:

improvisor40 left a comment (tinygo-org/tinygo#2446) https://github.com/tinygo-org/tinygo/issues/2446#issuecomment-3288354100

Yes its happening, but with the latest version of tinygo

— Reply to this email directly, view it on GitHub https://github.com/tinygo-org/tinygo/issues/2446#issuecomment-3288354100, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABKK5HXJMEBNWRKTTOYGDD3SQK7BAVCNFSM6AAAAABMSTHYYGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTEOBYGM2TIMJQGA . You are receiving this because you commented.Message ID: @.***>

gherlein avatar Sep 13 '25 17:09 gherlein

The multicore scheduler is automatically used on the rp2040 and the rp2350, you do not need to do anything special. In fact, you don't need to do anything to use this - if you start multiple goroutines, they will automatically be scheduled over the two available cores.

Closing, since this is now implemented.

aykevl avatar Sep 15 '25 15:09 aykevl

@aykevl is it enabled on Linux x64?

inliquid avatar Sep 18 '25 21:09 inliquid

Yes it is, i think its enabled on all latest builds

improvisor40 avatar Sep 18 '25 22:09 improvisor40

@inliquid yes, I added support on Linux first (using one thread per goroutine). MacOS works similar to Linux, but Windows isn't supported yet.

aykevl avatar Sep 23 '25 10:09 aykevl