I don’t know how this plays out for SWI-Prolog. The testing--- Synchronet 3.20a-Linux NewsLink 1.114
reported here by Jan W doesn’t test coroutines. It tests only
threads, increases the number of threads more and more.
Threads are not coroutines. You would need to provide some
special coroutine testing. And all you would possibly see that
there is no speed-up only that the cost goes up.
If the coroutine runs a Prolog engine, the costs for stackless and
the cost for stackfull can be also different. In stackless you don’t
need to create a new Prolog engine, you can reuse the existing
main Prolog engine. In stackfull you have some initial cost of
creating the Prolog engine and then you have the additional cost
of appropriately resuming the Prolog engine, besides the cost of
the event loop itself, the context switching there.
Unless you have a test case that has also some network I/O or
similar involved, i.e. processing done outside of the single thread
where the coroutine runs, you wont see much benefit of coroutines.
Not a benefit compared to threads, but a benefit of the coroutines
itself. Depending on how the network I/O scales, the coroutines will scale.
Another case of additional CPU resources would be for example
handing a bitmap to a GPU. Or even handing some machine learning
to a more versatile GPU. Or as microsoft recently does, it off-loads
some anti-virus checking code to a GPU. Coroutines can equally well
wait for results as threads can do, and coroutines do not need to
run in separate threads.
Mostowski Collapse schrieb am Samstag, 4. März 2023 um 14:09:55 UTC+1:
Well I must apologize. I was using the word fiber, especially
for a worker with event loop. But under more closer inspection
of the notion, a worker with event loop would support both
fibers and non-fibers, if we take this classification:
+--- subroutine
+--- coroutine
......+---- stackless
......+---- stackful (fibers)
In JavaScript the notion is a little bit blurred, since one can use setTimeout() both with stackful coroutines and stackless
coroutines. i.e. you can call setTimeout() with async function
which gives you a stackful coroutine, you need to call setTimeout()
only once. Or you can call setTimeout() with an ordinary function
which gives you a stackless coroutine, if you do this over and over again.
In Python the distinction is clearer. For example call_later() from
the event loop gives you a stackless coroutine, by the same method
of calling it over and over again, when the callback terminates. i.e. using continuation style re-scheduling. Or there is create_task()
from the event loop, which then gives you a stackfull coroutine.
So I doubt that anything what was said so far about fibers makes any sense. Especially since the above model deals with 1:N coroutines. Although Python has functions to inject a coroutine into an alien
thread. But in the 1:N coroutines model of a worker with an event loop
one has to look at different costs, costs for stackless
and costs for stackfull coroutines.
I now came up with the following API for event loop running--- Synchronet 3.20a-Linux NewsLink 1.114
in one thread, providing both 1:N fibers and non-fibers:
- Part 1: Callbacks (non-fibers)
They are Stackless and run in the main Engine of the Current Thread.
In my current take, they run without Auto-Yield, this is switched off, so
a Prolog flag heartbeat is needed which has a engine scope.
os_call_later(G, D, T):
The predicate succeeds in T with a new timer. As a side effect
it schedules the goal G to be executed after D milliseconds.
os_call_cancel(T):
The predicate succeeds. As a side effect it cancels the timer T.
- Part 2: Tasks (1:N fibers)
They are Stackful and create their own Engine in the Current Thread.
In my current take, they run with Auto-Yield, this is switched on, so
a Prolog flag heartbeat is needed which has a engine scope.
os_engine_current(E):
The predicate succeeds in E with the current engine.
os_engine_abort(E, M):
The predicate succeeds. As a side effect the engine E gets
the message M signalled.
os_engine_new(G, E):
The predicate succeeds in E with a new engine for the goal G.
os_engine_start(E):
The predicate succeeds. As a side effect the engine E gets
scheduled to be executed.
I am currently working on a proof of concept, to use the--- Synchronet 3.20a-Linux NewsLink 1.114
above elements to realize this high-level predicate, but
not with threads, but with auto-yielding coroutines:
first_solution(-X, :Goals, +Options) https://www.swi-prolog.org/pldoc/man?predicate=first_solution/3
What are the chances that this is possible? It would be
very useful, since one could run multiple theorem provers
in the browser, just like the thread version says, but now
doing it with corountines. This could work for Prolog WASM
in browser and nodeJS as well. The SWI-Prolog implementation
uses queues. I have no clue yet what the replacement
with coroutines would be.
Mostowski Collapse schrieb am Sonntag, 5. März 2023 um 13:48:34 UTC+1:
I now came up with the following API for event loop running
in one thread, providing both 1:N fibers and non-fibers:
- Part 1: Callbacks (non-fibers)
They are Stackless and run in the main Engine of the Current Thread.
In my current take, they run without Auto-Yield, this is switched off, so a Prolog flag heartbeat is needed which has a engine scope.
os_call_later(G, D, T):
The predicate succeeds in T with a new timer. As a side effect
it schedules the goal G to be executed after D milliseconds.
os_call_cancel(T):
The predicate succeeds. As a side effect it cancels the timer T.
- Part 2: Tasks (1:N fibers)
They are Stackful and create their own Engine in the Current Thread.
In my current take, they run with Auto-Yield, this is switched on, so
a Prolog flag heartbeat is needed which has a engine scope.
os_engine_current(E):
The predicate succeeds in E with the current engine.
os_engine_abort(E, M):
The predicate succeeds. As a side effect the engine E gets
the message M signalled.
os_engine_new(G, E):
The predicate succeeds in E with a new engine for the goal G.
os_engine_start(E):
The predicate succeeds. As a side effect the engine E gets
scheduled to be executed.
Try this little exercise:tick(0) :- !.
Engine 1 (Every Second):
animates a clock in the GUI
Engine 2 (Every Minute): calls async_process/4,
fetches the actual ₿ bitcoin rate,
and displays it
Ok here is a first solution for the challenge:--- Synchronet 3.20a-Linux NewsLink 1.114
Try this little exercise:
Engine 1 (Every Second):
animates a clock in the GUI
Engine 2 (Every Minute): calls async_process/4,tick(0) :- !.
fetches the actual ₿ bitcoin rate,
and displays it
tick(N) :- M is N-1, write('tick '), flush_output,
call_later(tick(M), 1000).
tock(0) :- !.
tock(N) :- M is N-1, write('tock '), flush_output,
call_later(tock(M), 5000).
It should display something along:
?- tick(11), tock(3), sleep(12000).
tick tock tick tick tick tick tock tick tick tick tick tick tock tick true.
Are there other solutions?
Yeah, Corona is over, the 90's are back:--- Synchronet 3.20a-Linux NewsLink 1.114
Example 1: Techno Musik is Back
(Remember Party Animals - Have You Ever Been Mellow)
Domiziana feat. Blümchen - SOS
https://www.youtube.com/watch?v=mlzA0R9kSTg
Example 2: No-GIL Virtual Machines are Back
(Remember Java Synced Vector and Hashtable 1995)
This PEP proposes using per-object locks https://peps.python.org/pep-0703/#container-thread-safety
But what about the new SWI-Prolog Janus Python Interface?--- Synchronet 3.20a-Linux NewsLink 1.114
Runs even with Python 3.12 it seems:
/* SWI-Prolog (threaded, 64 bits, version 9.1.14) */
?- assertz(file_search_path(path, '<your python runtime directory>')).
true.
?- py_version.
% Janus embeds Python 3.12.0b4
true.
But it doesn't provide a Prolog model on the Python side, this fails:
?- L = foo(bar), py_call(str(L), S).
ERROR: Domain error: `py_data' expected, found `foo(bar)'
So people from PySwip will not immediately flock to Janus?
Thats a large list of people using PySwip, it says 329 people!
https://github.com/yuce/pyswip
PySwip seems to provide a Prolog model on the Python side,
it has classes such as Functor, Variable, etc..
But its pretty dead, the last commit was Jan 18, 2023
Maybe there is a follow up project somewhere? Or
they are holding back, it says 0.2.11 (Not Released)?
Mild Shock schrieb am Samstag, 19. August 2023 um 18:46:00 UTC+2:
Yeah, Corona is over, the 90's are back:
Example 1: Techno Musik is Back
(Remember Party Animals - Have You Ever Been Mellow)
Domiziana feat. Blümchen - SOS https://www.youtube.com/watch?v=mlzA0R9kSTg
Example 2: No-GIL Virtual Machines are Back
(Remember Java Synced Vector and Hashtable 1995)
This PEP proposes using per-object locks https://peps.python.org/pep-0703/#container-thread-safety
Sysop: | DaiTengu |
---|---|
Location: | Appleton, WI |
Users: | 919 |
Nodes: | 10 (0 / 10) |
Uptime: | 70:49:18 |
Calls: | 12,185 |
Files: | 186,526 |
Messages: | 2,236,725 |