Raul Miller wrote:
What does "first" mean in the context of "parallel"? (Does it mean
anything different than "randomly choosen"?)
Skip says:
In the case of my "parallel" operation definition, "first" has a very
specific meaning. The parallel function I described is defined such that
it is impossible to start two or more parallel operations at the same
time. Of course, many parallel operations can be _executing_ at the same
time, but each of the operations must start in a sequential manner. By
definition, all parallel tasks started by the parallel function will
have a well defined, and well known, order of execution start. This
establishes a "priority" of parallel tasks, which helps to prevent the
types of conflicts that can arise when multiple tasks attempt to work on
the same data at the same time. So when I say "first", I mean the order
of execution start, which defines priority, nothing more. In your example:
'A B C'=: exp"0(4 4 4)
parallel each A;B;C
The order of starting of the functions A, B, and C must be defined. If
we say the order is start A, then start B, then start C, that defines
the start order. The actual delays between the consecutive starts could
be a few nanoseconds. Thus if A is started first, then any reference to
variables accessed or modified in A by B or C would be blocked until A
completed operations on that variable. It would be the job of the
interpreter to make sure this rule was enforced. If there are common
variables, the B & C processes would have to wait on the A process to
finish operating on the shared variable before they could operate on it.
Raul Miller wrote:
For that matter, what does "lock" mean? Does that mean that any attempt
to read that variable must wait until the other expression is complete?
Skip says:
The lower-priority parallel process doesn't necessarily have to wait
until the higher priority process has completely finished to access a
shared variable, but the lower task at least must wait until the
higher-priority process has completely finished with its work on the
shared variable, before it can proceed. .
Raul Miller wrote:
Or does it mean that writes to the variable are atomic?
Skip says:
No. Atomic writes would be a much more complex problem to prevent conflicts
Raul Miller wrote:
[Do you see how these can be different?] Or does it mean something else?
Skip says:
Yes, they are obviously different, and the second one is prohibited.
Raul Miller wrote:
What happens when thread A is waiting on thread B, but thread B is waiting on
thread A?
Skip says:
This will never happen with the parallel function, because the "first"
started parallel task, in this case A, will always preempt the other
started tasks. A will never wait on B, as A has priority on all variable
operations that may conflict between A & B (or C). B will always wait on
A if there are shared data operations because of this priority.
Similarly, B will never wait on C, as B has priority on all variable
operations that may conflict between B & C. C, being the low man on the
totem pole, will have to wait on anybody who is working on a variable
that they share in common.
This encourages the programmer to break up the data under work in such a
way to prevent shared access of the same data, if the programmer wants
to optimize parallelism. Otherwise, the program will run sequentially,
with little or no gain in execution speed. I learned this priority trick
to prevent parallel conflicts years ago, working on real-time parallel
schemes for character recognition engines.
Raul Miller wrote:
Consider:
a=:a,b
What happens here in a parallel context? (Remember that J allocates
up to double the strictly necessary space for arrays to make
this expression fast in the typical case.)
Skip says:
Since this example does not use the parallel function, there will be no
parallel execution of the assignment.
(Would it acceptable to make J substantially slower in
contexts where it's currently fast so that it can run multiple
threads?)
No. The interpreter should be designed to attempt parallelization
only if it will significantly speed up the execution of a
specific primitive.
I thought we were discussing your "parallel" operation, hinted at
above? Are you saying that certain primitives would throw an
error if they were used in one of these threads?
You are justified in being confused here. I was mixing discussions. My
response was about the parallelization of primitives. If primitives in J
were to support parallelism, then they should only resort to the
parallelism when it benefited performance, and not impact performance if
parallelism were not used. The parallelism should be invisible, and no
error should be thrown if parallelism was not deemed efficient enough to
use by the interpreter. A slight degradation in overall J performance (<
0.1%) would be acceptable to deal with the overhead in making the
parallel/no-parallel decision.
Moving to the coarse parallelism discussion, the parallel operation
should be a separate function in J, and should not impact the execution
of any code that was not requested to be run in parallel by the
programmer, using the parallel function..
Skip Cave
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm