 |
BorlandTalk.com Borland discussion newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Martin James Guest
|
Posted: Mon Nov 14, 2005 7:48 pm Post subject: Train crash, (index locking) |
|
|
I've got this array of pointers and two pointers to this array, one starts
off pointing at the top and the other pointing at the base:
dataArray=array[0..summat-1] of pointer;
...
basePointer:=@dataArray;
topPointer:=@dataArray[summat-1];
Two threads start off on this data, one eating it from the base and the
other from the top, inc-ing and dec-ing the index pointers. Eventually, the
two pointers will meet in the middle and both threads must realise that they
have hit each other with one thread, or the other, having cleanly eaten up
the last data value. The threads inc and dec the pointers via a method
function:
function incLow:boolean;
function decHigh:boolean;
so these functions should return 'true' if a data item is available via. the
changed index pointer, or 'false' if there is no more data.
How can I do this without a critical section? A CS here would be too slow
and inappropriate due to the tightness of the loop and large probability of
contention during the crash.
I should be able to work this out myself but I have a headache from the
multiThreaded sorts. I think I need beer.
Rgds,
Martin
|
|
| Back to top |
|
 |
Joe Bain Guest
|
Posted: Mon Nov 14, 2005 8:09 pm Post subject: Re: Train crash, (index locking) |
|
|
Martin James wrote:
| Quote: | I've got this array of pointers and two pointers to this array, one
starts off pointing at the top and the other pointing at the base:
|
Do you have to have one going bottom up and the other going top down?
If you pass each thread a begining pointer and an end pointer they may
not need any sort of sync to run.
--------------
Joe Bain
www.iegsoftware.com
|
|
| Back to top |
|
 |
Les Pawelczyk Guest
|
Posted: Mon Nov 14, 2005 9:02 pm Post subject: Re: Train crash, (index locking) |
|
|
| Quote: | How can I do this without a critical section? A CS here would be too slow
and inappropriate due to the tightness of the loop and large probability of
contention during the crash.
|
The possible solution would be to declare "basePointer" and "topPointer" in such a way as to occupy 8 bytes of contiguous memory (as in packed record for example) and then employing CMPXCHG8B with the LOCK prefix so every time you update one or the other, both of them are locked. Locking is going to be slow nevertheless, but should be faster that critical section.
Les.
|
|
| Back to top |
|
 |
Martin James Guest
|
Posted: Mon Nov 14, 2005 9:44 pm Post subject: Re: Train crash, (index locking) |
|
|
| Quote: |
I've got this array of pointers and two pointers to this array, one
starts off pointing at the top and the other pointing at the base:
Do you have to have one going bottom up and the other going top down?
|
Yes :)
| Quote: | If you pass each thread a begining pointer and an end pointer they may
not need any sort of sync to run.
|
Unfortunately, this is not possible :(
Depending on the data in the array, the actual speed of the two trains is
unknown <g>
It is possible that the data may be such that one thread consumes all the
data and the other thread none.
Basically, there are [number of processors] of these arrays containing data
that has been sorted. The data is then merged into one, large array by two
threads, one taking the overall minimum value from the bottom-up pointers of
these arrays and the other taking the overall max. value from the top-down
pointers. Once a thread has found which array contains the min/max value,
it loads this into the output array and then incs/decs the index of the
array that supplied the value.
It is possible, therefore, that a particular array has only large values and
so the thread that is extracting max. values will use up all the data from
this array before the thread extracting minimum values takes any - that
thread would meanwhile be extracting the small values from the other arrays
because it always finds that the lowest minimum value of all the other
arrays is always less than the minimum value of the array that happens to
contain large values, so it never gets round to extracting any minimums from
that array.
The more sorted the original data, the more likely this is to happen.
Rgds,
Martin
|
|
| Back to top |
|
 |
Martin James Guest
|
Posted: Mon Nov 14, 2005 9:46 pm Post subject: Re: Train crash, (index locking) |
|
|
| Quote: |
The possible solution would be to declare "basePointer" and "topPointer"
in such a way as to occupy 8 bytes of contiguous memory (as in packed record |
for example) and then employing CMPXCHG8B with the LOCK prefix so every time
you update one or the other, both of them are locked. Locking is going to be
slow nevertheless, but should be faster that critical section.
Er.. hmm.. I need beer to think about this :)
Thanks,
Martin
|
|
| Back to top |
|
 |
Cristian Nicola Guest
|
Posted: Tue Nov 15, 2005 9:56 am Post subject: Re: Train crash, (index locking) |
|
|
Very simple and elegant I was about to suggest this option :D
Cristian Nicola
to swap use something like:
function CAS(aDestAddr: pointer; v1: pointer; v2: integer; n1: pointer; n2:
integer): boolean;
asm
push ebx
push esi
mov esi, aDestAddr
mov eax, v1
mov edx, v2
mov ebx, n1
mov ecx, n2
{ LOCK cmpxchg8b qword ptr [esi] }
db $F0,$0F,$C7,$0E
sete result
pop esi
pop ebx
end;
and pass:
aDestAddr : the address of record holding the 2 values
v1: old base
v2: old top
n1: new base
n2: new top
In case of first function new base = old base, new top = old
top -sizeof(pointer)
In case of second function new base = old base + sizeof(pointer), new top =
old top.
"Les Pawelczyk" <les_at_pixelpointpos_dot_com> wrote
| Quote: |
The possible solution would be to declare "basePointer" and "topPointer"
in such a way as to occupy 8 bytes of contiguous memory (as in packed record |
for example) and then employing CMPXCHG8B with the LOCK prefix so every time
you update one or the other, both of them are locked. Locking is going to be
slow nevertheless, but should be faster that critical section.
|
|
| Back to top |
|
 |
Cristian Nicola Guest
|
Posted: Tue Nov 15, 2005 10:00 am Post subject: Re: Train crash, (index locking) |
|
|
Forgot to important things:
TYourRecord = record
Top: pointer;
Bottom: pointer;
end;
and creating a new record should be 8 byte aligned (so using normal var, or
normal memory allocation functions is NOT enough)...
Cristian Nicola
ps:
{ allocates a 8-byte align node }
function AllocMem8(size: integer): pointer;
var
p: pointer;
begin
result:= nil;
GetMem(p, size + ;
if (p = nil) then
exit;
case (integer(p) and $0000000F) of
$0, $8: result:= pointer(integer(p) + ;
$4, $C: result:= pointer(integer(p) + 4);
end;
if (result <> nil) then
pointer(pointer(integer(result) - 4)^):= p
else
FreeMem(p);
end;
{ deallocates a 8-byte aligned node }
procedure FreeMem8(var p: pointer);
begin
if (p <> nil) then
begin
FreeMem(pointer(pointer(integer(p) - 4)^));
p:= nil;
end;
end;
"Cristian Nicola" <n_cristian (AT) hotmail (DOT) com> wrote
|
|
| Back to top |
|
 |
Cristian Nicola Guest
|
Posted: Tue Nov 15, 2005 10:07 am Post subject: Re: Train crash, (index locking) |
|
|
Forgot another thing:
CAS function would return false if the values have changed so the algorithm
should be:
while true do
begin
{ preserve values }
oldtop:= myrec^.top;
oldbottom:= myrec^.bottom;
{ compare the collision }
if oldtop = oldbottom then
begin
{ collision }
break;
end
else
begin
{ move one end }
if cas(myrec, oldtop, oldbottom, oldtop, oldbottom - sizeof(pointer))
then
break;
end;
end;
"Cristian Nicola" <n_cristian (AT) hotmail (DOT) com> wrote
| Quote: | Very simple and elegant I was about to suggest this option
|
|
|
| Back to top |
|
 |
Martin James Guest
|
Posted: Tue Nov 15, 2005 10:51 am Post subject: Re: Train crash, (index locking) |
|
|
Thanks everybody!
I will try Les/Cristian 'LOCK CMPXCHG8B', (I remember when opcode mnemonics
were only 3 chars long - now longer than high-level language identifiers).
I was also thinking of Joe's comment.
Down at the pub last night, I thought of a cunning, 'composite' plan that
avoids most of the locking overhead. The thread-manager that runs the
threads can issue a work-request for each 'train' with a count for each
thread that is [half of one array length-1]. Even if both threads then
happen to suck on the same array, they will not be able to reach each other
and crash, so no slow locking is required. When these tasks are both done,
the 'closeness of the trains' in each array is checked. If they are still
all well apart, the tasks re-issue themselves with a count of [half of
smallest closeness-1]. Eventually, the trains in one or more of the arrays
wil be so close that there is no advantage of going through a thread-manager
dispatch cycle again. Both tasks will then be re-issued with an instruction
to continue to completion, but using the slow bus lock mechanism with the
world's longest opcode mnemonic.
Rgds,
Martin
|
|
| Back to top |
|
 |
Cristian Nicola Guest
|
Posted: Tue Nov 15, 2005 11:02 am Post subject: Re: Train crash, (index locking) |
|
|
Really nice site:
http://faydoc.tripod.com/cpu/index.htm
Cristian
"Martin James" <mjames_falcon (AT) dial (DOT) pipex.com> wrote
| Quote: | Thanks everybody!
I will try Les/Cristian 'LOCK CMPXCHG8B', (I remember when opcode
mnemonics
were only 3 chars long - now longer than high-level language identifiers).
|
|
|
| Back to top |
|
 |
Martin James Guest
|
Posted: Tue Nov 15, 2005 1:09 pm Post subject: Re: Train crash, (index locking) |
|
|
Thanks very much!
Rgds,
Martin )
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|