ACL and multi-processors
This is a somewhat complex issue, so this answer is broken up into
two parts.
The short answer
ACL can take advantage of multiple processors only on our :os-thread
ports. Currently, this is only on Windows.
If one is using an :os-threads port, the possibility of taking
advantage of multiple processors then depends on the structure of
the application in question. It is not possible for multiple threads
running Lisp code to access the lisp heap at the same time. But, if the
application has any number of threads that are running in foreign code
(and don't need to access the lisp heap), then these threads can
benefit from scheduling over multiple processors.
If memory sharing is not a significant factor, ACL -can- take advantage of
multiple-processors if you run a number of independent ACL processes (distinct
lisp images).
The longer answer
There are a number of parts to the more comprehensive answer...
:os-threads:
The Lisp heap
Heap is a technical word to describe the area in memory where space
is dynamically allocated whenever objects are created, or functions are
defined. This is a pretty much global concept that applies to most, if
not all, programming languages (not just Lisp). Where this becomes
significant is in the realm of memory management.
Memory Management: garbage collection
Applications are generally considered greedy (particularly on machines used
by multiple people, or by multiple applications) if they consume vast
quantities of memory. Hence, memory management was born. As applications
run, they tend to consume more and more memory through the creation of
various objects for data storage. Oftentimes, however, data may be
short-lived--it is only needed for a small period of time and then
can be disposed of.
Memory management is the means by which such data can be cleared
away to make room for new data without hogging all available memory.
In C/C++ applications, memory-management is at the discretion of the
application writer: memory can be consumed (malloc'd, which stands
for 'memory allocation') and then free'd when and how they wish to
do so.
The problem with the C/C++ approach is that a fair amount of time spent
writing an application is spent focusing on these memory management
issues; a problem only indirectly related to the actual problem of
getting the application to work.
Lisp (as well as Java and some other less-widespread programming
languages) makes use of automatic memory management, thus taking
away the burden of having to do so from the programmer. As a program
consumes more and more memory, a garbage collector kicks in and,
scanning through the heap, separates the useable data from the unusable.
There are a number of algorithms for how this can be done. ACL makes use
of a stop-and-copy garbage-collection algorithm. When a
garbage-collection occurs, Lisp stops processing any running application
(the stop part) and finds all objects in the heap that can still be
used by the application: all the live objects. All the live objects
are then copied into a new heap, leaving out all the dead objects.
<some kind of visual example here>
Garbage collection vs. multiprocessing (and multi-processors)
Garbage collection significantly impacts the use of Lisp on multiple
processors machines in three ways:
- Garbage collection moves live objects to different locations in
memory.
The stop-and-copy algorithm copies live objects to a new
location in memory. This means that if a garbage collection occurs, it is
Lisp's responsibility to make sure that any references to a given object
get updated to point to the new location the object has been copied to.
Otherwise, the reference will end up pointing to some random, meaningless
location. (Java use a mark-and-sweep GC algorithm, so it does not
have this problem, although there are other drawbacks to mark-and-sweep).
- A GC can happen at (almost) any time while lisp code is running.
Consider a lisp application that has 3 running lisp-processes,
each of which has a variable that references some object foo. If
a garbage collection occurs while process-1 is running and the foo object
gets moved to a new location in memory, the reference to foo in process-1
can be updated, but not the references in process-2 and process-3. Thus,
if process-2 becomes active and tries to access foo, an error will occur
and the application will crash.
At least, this is the way things currently stand, and it is
the problem that must be solved in order for us to implement a fully
multi-threaded lisp.