PDA

View Full Version : MultiCore issues



arthurprs
28-03-2008, 02:16 AM
hy guys i'm getting really beautifull problems here, program crash on dual core processors (or quad...) :lol:

i already spotted the problematic code and
im trying to use Critical_Section, but i'm not sure if i have to encapsulate ALL variables with it (even integers?)

someone can give me some tips?

ps: any article or text

Memphis
28-03-2008, 04:09 AM
how do you mean include them all ?

a critical section is used for blocking threads from accessing multithreaded objects... basically objects you will write to and read from, however it depends on you use the var for example a stringlist

for i := 0 to 3000 do [....]

using a critical section here is a good idea if 1 thread may delete an object which will give u an access violation... however if you just read from the list and dont change data, then there is no point using a critical section on that part of the code...

also try to use more then 1 critical section for different parts of your code / function....

so for example....

not good:

EnterCriticalSection(cs);
for i := 1 to 1000 do
Check(mystrllist[i]);

for i := 1 to 100 do
Check(anotherlist[i]);
LeaveCriticalSection(cs);


better:

EnterCriticalSection(cs_a);
for i := 1 to 1000 do
Check(mystrllist[i]);
LeaveCriticalSection(cs_a);

EnterCriticalSection(cs_b);
for i := 1 to 100 do
Check(anotherlist[i]);
LeaveCriticalSection(cs_b);


didnt quite understand what you meant, but hopefully this helps. if not let me know.

-Meka][Meka

arthurprs
28-03-2008, 05:25 PM
thats not what im in doubt, i know that i have to use a differents CS,

the problem is,

is Cardinal and String ThreadFree?

AthenaOfDelphi
28-03-2008, 08:19 PM
Whether or not you have to protect all variables with critical sections (or things like TMultiReadExclusiveWriteSynchronizer) depends on what they are used for and how they are accessed, and the affect that changing them could have.

For example, consider this...


if (x>=0) and (x<items.count) then
begin
// x is changed here by a.n.other thread
myItem:=items[x];
end;


Here, you are only reading X, but if X is changed by another thread where I've indicated to say -1, the next line in this thread will go boom.

You need to give careful consideration to cross thread storage and control mechanisms BEFORE you start seriously coding. One major tip is to define in advance all the critical sections you are going to use and define an order in which you will enter them and leave (the reverse of entering)... then once you've defined it, stick to it rigidly. That way, you can reduce the chances of deadlock.

AthenaOfDelphi
28-03-2008, 08:32 PM
I've just realised there is another interpretation of your question...

You could be talking about having one critical section per variable???

If so, the answer is no... don't do it... the overheads would be massive. Think logically about your data and protect the variables in logical blocks.

And now, I've just re-read your last post... DOH!! I should read more carefully before I fire up my keys.... in short... any data storage mechanism within Delphi cannot (and should not) be considered thread safe except perhaps TThreadList (I think thats what it's called). If its likely to be accessed (by that I mean read and simultaneously written to) by multiple threads, then it will need protection... either its own or a larger logical group.

JSoftware
28-03-2008, 09:18 PM
operations on a cardinal are threadsafe. Operations on strings are not threadsafe. Operations on pchar's are sometimes threadsafe.. :P

This has to do with atomicity. Cardinals are 32bit and can be contained in a cpu register. All math operations on 32 bit integers are atomic, except for more advanced operations such as sqrt, ln, etc.

Atomic operations mean that you can be sure that nothing will blow up. This means that you cannot consider memory operations(where you typecast a pointer to a simple type(pbyte, pword, pcardinal, etc)) atomic by default. Also, most operations on complex types such as records typically aren't threadsafe either.

arthurprs
28-03-2008, 09:19 PM
Whether or not you have to protect all variables with critical sections (or things like TMultiReadExclusiveWriteSynchronizer) depends on what they are used for and how they are accessed, and the affect that changing them could have.

For example, consider this...


if (x>=0) and (x<items.count) then
begin
// x is changed here by a.n.other thread
myItem:=items[x];
end;


Here, you are only reading X, but if X is changed by another thread where I've indicated to say -1, the next line in this thread will go boom.

You need to give careful consideration to cross thread storage and control mechanisms BEFORE you start seriously coding. One major tip is to define in advance all the critical sections you are going to use and define an order in which you will enter them and leave (the reverse of entering)... then once you've defined it, stick to it rigidly. That way, you can reduce the chances of deadlock.

=/ thats bad, i will have to make some functions insted of getting from the variable

are you sure that even integers and strings have to be encapsulated by CS's ?

Memphis
28-03-2008, 11:17 PM
are you sure that even integers and strings have to be encapsulated by CS's ?

again that all depends on what operations you are performing on the ints and strings....

read AthenaOfDelphi's first post carefully.

arthurprs
29-03-2008, 01:25 AM
are you sure that even integers and strings have to be encapsulated by CS's ?

again that all depends on what operations you are performing on the ints and strings....

read AthenaOfDelphi's first post carefully.

Inc() and Dec() on the cardinals

and simple assignment := on strings

Mirage
29-03-2008, 04:57 PM
Operations should be protected by critical sections (or other means) only if there is a chance of simultaneous access to the variable from different threads. So if one thread perforns Inc(a), and other Inc(b), you don't have to protect anything. But if the both threads performs Inc(a), you should protect the corresponding code. Type of a and b doesn't matter.

arthurprs
29-03-2008, 05:08 PM
if one of the threads only read an Cardinal i have to protect the acess?

ps: sorry for the bunch of question, i don't have a Dual Core processor to test ;/

Memphis
29-03-2008, 05:23 PM
if one of the threads only read an Cardinal i have to protect the acess?

ps: sorry for the bunch of question, i don't have a Dual Core processor to test ;/

if it is only reading from a value, then no, you do not need to

AthenaOfDelphi
29-03-2008, 08:23 PM
if one of the threads only read an Cardinal i have to protect the acess?

ps: sorry for the bunch of question, i don't have a Dual Core processor to test ;/

if it is only reading from a value, then no, you do not need to

This is a misleading answer... Mirage summed it up best. If there is the possibility that one thread will read, while another writes to the same variable /record/object, then you should protect ALL access to it accordingly.

If you have blocks of code that read and write, then protect them with critical sections. If you do more reading than writing, then you may get a performance benefit from using TMultiReadExclusiveWriteSynchronizer which allows simultaneous reads from lots of threads, but will completely block everything when one thread attempts a write.

You should assume nothing about atomic operations or execution sequence, nothing... except, that if it can go wrong, you can guarantee it will. So, my advice is think carefully about cross thread interactions... where possible keep it to an absolute minimum, and if you can't, try and group variables together into logical blocks that are likely to get updated together and protect the group... this will help keep the overheads down.

I should also point out, that without running on a dual core or dual CPU machine, you will not find all the potential problems, its impossible as you will only ever have a single thread of execution. To get the real nasty problems you need multiple threads of simultaneous execution... you can only get that on dual core or dual CPU machines.

arthurprs
29-03-2008, 08:38 PM
Thanks for the answers guys, i have solved the problem with 2 CriticalSections :wink:

Memphis
29-03-2008, 10:52 PM
if one of the threads only read an Cardinal i have to protect the acess?

ps: sorry for the bunch of question, i don't have a Dual Core processor to test ;/

if it is only reading from a value, then no, you do not need to

This is a misleading answer...

it is not misleading at all, if you read correctly.
if it is only reading

-MM

JSoftware
29-03-2008, 10:56 PM
Memphis, it is misleading unless you can ensure atomicity when writing to the variable from somewhere else

Memphis
30-03-2008, 08:04 PM
Memphis, it is misleading unless you can ensure atomicity when writing to the variable from somewhere else

and as he asked, if it is 'only' reading.... now it is not misleading at all, like i said.. IF it is only READING then no, if 2 threads read from the same variable, it is not a problem at all... and in an earlier post i also said to read athenaofdelphis post about IF writing to a variable also ( in which case it would cause a problem ) ... now i rest my case....

JSoftware
30-03-2008, 08:59 PM
Memphis, it is misleading unless you can ensure atomicity when writing to the variable from somewhere else

and as he asked, if it is 'only' reading.... now it is not misleading at all, like i said.. IF it is only READING then no, if 2 threads read from the same variable, it is not a problem at all... and in an earlier post i also said to read athenaofdelphis post about IF writing to a variable also ( in which case it would cause a problem ) ... now i rest my case....
It's not a problem if two threads read from it but that was not what arthurps asked about. He asked if it was ok if one of the threads were reading the variable. That would imply that some other thread will write to it. You can't guarantee that this won't blow up

AthenaOfDelphi
30-03-2008, 09:00 PM
Before this descends into a total flame war...

I think we (that is I, JSoftware, Memphis and Mirage) are all pretty much singing from the same song sheet.

If you can guarantee that a variable will only ever be read by multiple threads, the protection is not required. If however one of those could write to it, then protection is most likely required.

That I think sums it up nicely.