On 4/3/2012 9:46 AM, Miles Fidelman wrote:
David Barbour wrote:

On Tue, Apr 3, 2012 at 8:25 AM, Eugen Leitl <[email protected] <mailto:[email protected]>> wrote:

    It's not just imperative programming. The superficial mode of human
    cognition is sequential. This is the problem with all of mathematics
    and computer science as well.


Perhaps human attention is basically sequential, as we're only able to focus our eyes on one point and use two hands. But I think humans understand parallel behavior well enough - maintaining multiple relationships, for example, and predicting the behaviors of multiple people.

And for that matter, driving a car, playing a sport, walking and chewing gum at the same time :-)


yes, but people have built-in machinery for this, in the form of the cerebellum. relatively little conscious activity is generally involved in these sorts of tasks.

if people had to depend on their higher reasoning powers for basic movement tasks, people would likely be largely unable to operate effectively in basic day-to-day tasks.



    If you look at MPI debuggers, it puts people into a whole other
    universe of pain that just multithreading.


I can think of a lot of single-threaded interfaces that put people in a universe of pain. It isn't clear to me that distribution is at fault there. ;)


Come to think of it, tracing flow-of-control through an object-oriented system REALLY is a universe of pain (consider the difference between a simulation - say a massively multiplayer game - where each entity is modeled as an object, with one or two threads winding their way through every object, 20 times a second; vs. modeling each entity as a process/actor).


FWIW, in general I don't think much about global control-flow.

however, there is a problem with the differences between:
global behavior (the program as a whole);
local behavior (a local collection of functions and statements).

a person may tend to use general fuzzy / "intuitive" behavior for reasoning about "the system as a whole", but will typically use fairly rigid sequential logic for thinking about the behavior of a given piece of code.

there is a problem if the individual pieces of code are no longer readily subject to analysis.


the problem I think with multithreading isn't so much that things are parallel or asynchronous, but rather that things are very often inconsistent.

if two threads try to operate on the same piece of data at the same time, often this will create states which are impossible had either been operating on the data individually (and, very often, changes made in one thread will not be immediately visible to others, say, because the compiler had not actually thought to write the change to memory, or the other thread to reload the variable).

hence, people need things like the "volatile" modifier, use of atomic operations, things like "mutexes" or "synchronized" regions, ...


this leaves several possible options:
systems go further in this direction, with little expectation of global synchronization unless some specific mechanism is used (two threads working on a piece of memory may temporarily each see their own local copy); or, languages/compilers go the other direction, so that one thread changing a variable is mandated to be immediately visible to other threads.

one option is more costly than the other.

as-is, the situation seems to be that compilers lean on one side (only locally consistent), whereas the HW tries to be globally consistent.

a question then, is assuming HW is not kept strictly consistent, how to best handle this (regarding both language design and performance).


however, personally I think abandoning local sequential logic and consistency, as being a bad move.

I am personally more in-favor of message passing, and either the ability to access objects synchronously, or "pass messages to the object", which may be in-turn synchronous.

consider, for example:
class Foo
{
sync function methodA() { ... } //synchronous (only one such method executes at a time)
    sync function methodB() { ... }    //synchronous
async function methodC() { ... } //asynchronous / concurrent (calls will not block) sync async function methodD() { ... } //synchronous, but calls will not block
}

...
var obj=new Foo();

//thread A
obj.methodA();
//thread B
obj.methodB();

the VM could enforce that the object only executes a single such method at a time (but does not globally lock the object, unlike "synchronized").

similarly:
//thread A
async obj.methodA();
//thread B
async obj.methodB();

which works similarly, except neither thread blocks (in this case, "obj" functions as a virtual process, and the method call serves more as a message pass). note that, if methods are not "sync", then they may execute concurrently.

note that "obj.methodC();" will behave as if the async keyword were given (it may be called concurrently). "obj.methodD();" will behave as if it were a synchronous method called asynchronously.

this allows deliberately asynchronous behavior (and more ability to optimize for a multi-processor system), but at the same time, does not hinder the use of synchronous logic.

similar behavior can be applied to blocks:
async { ... }    //block does not block
sync { ... }  //block will block


as-is, most of this stuff uses "green threads" (and some amount of internal locking), so it is less certain how to best map it to real HW.

I can imagine some how to map it to either "CPUs with inter-processor interrupts", or to something like TCP or UDP, which could be "close enough" (like, if a hugely multiprocessor system were implemented in a form resembling a bunch of simpler shared-memory multiprocessor systems connected over a network or similar).


FWIW, as-is, I don't really make all that intensive use of multithreading. my code is, technically, multithreaded, but most of the code is itself still largely single-threaded, and most threads are based on "subdivision by task" rather than "parallel execution".

for example:
a thread to manage the GC;
another thread to manage the "TRNG". it tries to generate true random numbers based on the assumption that the noise patterns seen in "rdtsc" deltas represent "true" entropy (basically, it is a loop which does little more than sleep and call rdtsc, and add the values seen into a random number generator);
also the VM green-thread workers, and several other misc threads.


a recent consideration was to move video recording/encoding to its own thread, due to the apparent lag-inducing behavior of the current video recording (which operates in the same thread as my 3D renderer, resulting in a notable drop in framerate whenever video recording is active). granted, this is partly because I am using MJPG, and my JPEG encoder has a hard time keeping up with encoding full-resolution (800x600 in this case) screen-shots in a timely manner: individually, both the video recording and 3D renderer pull off around 40fps, but when used together, the overall framerate is more around 10-15fps.

yes, it is much faster to dump truecolor video to disk, but this rapidly eats up HDD space (around 1GB/min with 16bpp output). blarg... currently, video-recording isn't a major use-case though.


or such...

_______________________________________________
fonc mailing list
[email protected]
http://vpri.org/mailman/listinfo/fonc

Reply via email to