Given the core model of objects that are independent computing engines (storage being instance vars, CPU being the class methods) responding to messages passed from one to the other, it would seem that Smalltalk would be a natural fit for parallel processing on massive numbers of cores. Yet this is an area where Smalltalk is still very weak indeed, replying on its own simulated multitasking features which do not exploit modern processors' hardware capabilities.
Why is this? What are the main problems? Is mutability the key, or is it something more specific to Smalltalk?
Difficulty ? None
Just launch multiple Pharo instances and have them communicate via sockets or save their final data to a common file. Your OS will manage each instance and send it to execute in a diffirent core. OSProcess module offers such functionality and have been successful implementations like Hydra and RoarVM , the problem is none use them.
Actually the hardest thing of parallelism is to get people using it. With todays hardware applications rarely hit the 100% of a single core. I have barely made Pharo go above 10%.
Also like many programming dynamic programming languages Smalltalk is a developer performance language and not a application performance language.
If you really have such a heavy processing problem you should be using languages like C and C++ that are very application performance orientated languages. Not only its way harder to use those language but even parallelism is very hard to do right even with the right library. The hardware is very weird design wise and there like a ton of gotchas you have to be aware of.
And this is why parallelism suits those programming languages better. Of course you could make libraries in C/C++ and have Pharo or other smalltalks use them. Python does this. Python and Pharo are quite similar in that both they use a GIL and have green threads. The gotcha is that you will have to join your threads back to the main thread in order for the VM to have direct access to it but there are ways around this like I said, socket communication, pipes, Shared memory mapped files and much more.
Python's parallel libraries are all C/C++ based.
Parallelism itself is a very tricky subject , even if you have parallelism its possible that your code will be as slow as running on a single thread and single core. But that is a general problem with application performance , the moment you want to milk out as much power as you can you have to know how hardware works.
Hardware itself nowdays is super complex. Language is the least of your concerns.
So totally possible in Smalltalk but frankly there are not that many people interested into it. I have seen questions on parallelism in the Pharo mailing lists that I frequent that last 2 years, maybe once or twice . And even for concurrency its very rare for someone to ask a question about it.
First of all, let's recall that GemStone proves that Smalltalk can be extended to support parallel computing. Of course, the question remains because GemStone is a very sophisticated system (think, e.g., in the Garbage Collector!) and all other dialects don't behave that way.
Parallel computing requires thread-safe code; otherwise race conditions would emerge all the time. The problem is that making Smalltalk code thread-safe would add complexity everywhere. Consider for instance
OrderedCollection >> addLast: anObject
lastIndex = array size ifTrue: [self makeRoomAtLast].
lastIndex := lastIndex + 1.
^array at: lastIndex put: newObject
An interruption between these lines of code could leave the internal state of the receiver inconsistent. Of course, this could also happen with non-parallel execution because Smalltalk supports interruptions. However, the way Smalltalk uses this capability is limited to critical sections that do not happen so often and are therefore somehow under control.
The reason why the addition of thread-safe code is not so natural in Smalltalk is that in Smalltalk we have an image. This means that there are lots of objects shared by all processes, including for example, all the classes, compiled methods, etc. The dynamic nature of Smalltalk, which is used extensively by the system and its applications, makes things even harder.
In my personal experience a good way to achieve multi-core capabilities in Smalltalk is to launch different OS processes (instances of a headless image) and coordinate them using Smalltalk semaphores and processes. Under this approach, every OS process is represented in the main image (the one with a UI) by a Smalltalk process. The communication between the main image and the headless processes can rely on sockets (or any other feature). Of course, you pay a price when debugging. In fact, you end up tracing lots of events in log files and opening debuggers in the "headless" processes until you understand what went wrong. But can be done, not just as a demo but for a real "industrial-strong" product.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With