newLISP to get Cilk-style concurrency

Multi-processing in newLISP can be a chore. All processes must be directly known to any others that will be accessing shared memory, which must be synchronized using semaphores. A new development release of newLISP (9.3.7) will change all that by adding Cilk-style primitives.

The Cilk project is a parallel programming language based on C. Its goal is to radically simplify concurrency in C applications. Cilk applications are first compiled to C. Cilk adds simple concurrency syntax and a scheduler to determine whether or not to launch a new thread or simply execute the code block. Here is a sample from the Cilk website:

cilk int fib (int n)
{
    if (n > 2) return n;
    else
    {
        int x, y;
 
        x = spawn fib (n-1);
        y = spawn fib (n-2);
 
        sync;
 
        return (x+y);
    }
}

The next version of newLISP will have the spawn, sync, and abort functions. Here is the same function, written in newLISP:

(define (fib n)
  (if (> n 2) 1
    (begin
      (spawn 'x (fib (- n 1)))
      (spawn 'y (fib (- n 2)))
      (sync 10000)
      (+ x y))))

There are a few notable differences.
spawn not only spawns a new process, but it also sets the target symbol to be assigned when sync is run.
sync itself has a millisecond timeout. There is currently no scheduler and sync cannot block indefinitely, but hopefully these will be added in the full release.

spawn returns the pid of the launched child process, which may be cancelled later using (abort pid). On its own, abort cancels all child processes.

sync causes the current process to block until all children have completed or the timeout (in milliseconds) is reached. An interesting addition is that sync can also be used as a predicate to determine if all child processes have quit:

(until (sync 10000)
    (println "Waiting... (foot-tapping)")
    (sleep 100))

By itself, it returns a list of pids of child processes:

(spawn 'foo (+ 1 1))
(spawn 'bar (+ 2 2))
(sync) ; =>(12345 12346)
(sync 100) ; => true
foo ; => 2
bar ; => 4

Underneath the hood, the new functionality is not using Cilk – it simply aims to add similar behavior to newLISP. Because of newLISP’s small size (~500 KB in memory), forked processes (in the typical sense, not the Erlang one) are cheap. With sync functionality, newLISP will have a real edge on languages using OS threads.

In other news

Another recent development release of newLISP (9.3.5) added another important feature – the ability to pre-compile regular expressions:

(set 're (regex-comp "(foo|bar)"))
(regex re "raising the bar" 0x10000)

The new regular expression int-optin, 0x10000, alerts the regex function to expect a precompiled pattern. This works in all regex functions.

Leave a comment | Trackback
Apr 3rd, 2008 | Posted in Programming
No comments yet.