Doing something as "at the same time" as possible

I know beam makes a scheduler per CPU (OS thread); so theoretically I can do something at exactly the same time up to the number of CPUs I have.

What is the best way to kick them all off at the same time? Is my only option to send (via Process.send or Kernel.send) a message to a process running on each scheduler? If I do that, the messages are sent out serially. Any alternative techniques or should that be considered fast enough in this ecosystem?

I posted a similar post, but I think it was too complex to bother with.

The type of question you’re asking I think requires some definitions. There is, at the end of the day, no such thing as truly “at the same time” there is “measured to be within a time bound by an observer”. How tight does the time bound need to be? Why? Who is observing this?

3 Likes

I think you need to clarify what you mean by “at the same time”, as it’s not well-defined with communicating processes. All it takes is one piece that forces serial behavior to mess things up.

A better approach is to code things to not need guarantees about simultaneity. For instance, in a network-performance situation like your previous post, instead of:

  • start a bunch of connections and a timer simultaneously
  • wait for all the connections to finish
  • read the timer

something like:

  • start a bunch of connections quickly
  • each connection starts a timer when it begins
  • each connection reads its timer at the end
  • each connection sends the timing to the main process
  • the main process waits for all the results, and then averages etc them appropriately

You could check how others are doing it.

Maybe you could tell your processes to start at a specific point in time
https://www.erlang.org/doc/man/erlang#monotonic_time-0
then just have them sleep and check time repeatedly.

/one more thing
I don’t think you can choose the specific scheduler a process is on.
:erlang.system_info(:scheduler_id)
I guess if you spawn enough processes under load it should be spread out to all available schedulers.

Thanks for the replies, all!

@benwilson512, I think the context you might be seeking is in the linked original post. That post didn’t gent any replies; so I made this post much shorter and simpler. By “at the same time”, I mean parallelism. The goal is to squish that time bound as much as possible in BEAM. I know for other languages the solution would be to start a thread per CPU core.

@al2o3cr, yeah, I think my desires are leaving the realm of practical and entering theoretical (at least in BEAM land). I do have a desire for that TCP SYN to drop in on server/listener to be parallel as possible in BEAM land. Insofar as your recommendation, it’s totally the practical way to do it and may end up what I do if I can’t find what I’m looking for.

@schneebyte, I have seen stressgrid, but not the others. Thanks for the links! I had considered a timer-based kick-off, but wasn’t sure the best way to do it in Elixir/Erlang since I was under the impression that time was pretty squishy in BEAM land.

Regarding choosing specific schedulers, I thought PartitionSupervisor would help partition its children across schedulers. Do I have that messed up in my head?