atemerev / skynet

Skynet 1M threads microbenchmark
MIT License
1.05k stars 122 forks source link

Prolog version! #58

Open ghost opened 8 years ago

ghost commented 8 years ago

Out of interest I have included my own implementation in Prolog. This is written in my own Prolog ( https://github.com/infradig/yxtrang ) which implements Erlang-style processes and message-passing. It is quite slow as I haven't done too much optimisation in this area (in fact I just got it working well-enough to run the test at all).

:-module(skynet).
:-export([start/2]).

start(Size,Div) :-
        spawn(skynet(0,Size,Div)),
        recv(Tot),
        writeln('###=> ',Tot).

skynet(Num,1,Div) :- send(Num).

skynet(Num,Size,Div) :-
    NewSize is Size div Div,
    between(1,Div,Idx),
        NewNum is Num+((Idx-1)*NewSize),
        spawn(skynet(NewNum,NewSize,Div)),
        fail.

skynet(Num,Size,Div) :- process_sum(0,Div).

process_sum(Tot,0) :- send(parent,Tot).

process_sum(Tot,Idx) :-
    recv(N),
    NewTot is Tot+N,
    NewIdx is Idx-1,
    process_sum(NewTot,NewIdx).

It would be trivially easy to distribute the skynet processes over multiple nodes, as send/recv work transparently over networks as well.

ghost commented 8 years ago

$ ./yxt samples/skynet '--goal=skynet:start(1000000,10)' Yxtrang v0.1alpha, 64-bits, Feb 17 2016 Consult default => 'samples/skynet'

=> 499999500000

(13.814 s) yes

Can get it down to around 7 seconds by specifying a thread-pool size of 1 (--tpool=1), in effect forcing it to serialize. Prevents cache-thrashing I suppose.

ghost commented 8 years ago

Came back to it recently. Just over 3 seconds now.