The lockset() and lockclr() mechanisms on the P2
samuell
Posts: 554
in Propeller 2
Hi,
ersmith mentioned that using lockset() and lockclr() can hog the locks and cause a race condition on the P2. I wanted to know more about that mechanism. In fact, if I remove lockset and lockclr from the infamous prime number program code, it runs faster. That is very different from what happened on the P1. The post that brought my attention can be seen here:
http://forums.parallax.com/discussion/170148/a-compilation-of-test-code-for-the-p2-eval
However, I want do dedicate a new thread just for understanding the nature of the problem. Is it an issue? Or the lockset()/lockclr() mechanisms are now implicit (in hardware)?
Kind regards, Samuel Lourenço
ersmith mentioned that using lockset() and lockclr() can hog the locks and cause a race condition on the P2. I wanted to know more about that mechanism. In fact, if I remove lockset and lockclr from the infamous prime number program code, it runs faster. That is very different from what happened on the P1. The post that brought my attention can be seen here:
http://forums.parallax.com/discussion/170148/a-compilation-of-test-code-for-the-p2-eval
However, I want do dedicate a new thread just for understanding the nature of the problem. Is it an issue? Or the lockset()/lockclr() mechanisms are now implicit (in hardware)?
Kind regards, Samuel Lourenço
Comments
The issue is that if you have several COGs all doing: You can get into a situation where, say, COG 1 and COG 2 keep trading ownership of the lock, and so COG 3 never gets a chance to run. This is a problem if the "do some stuff" code at some point relies on a result that COG 3 should calculate; then you end up in a deadlock and the program never finishes.
In general you should never require a lock to be acquired before reading any variable; locks should only be used to protect writes. That still doesn't guarantee that a deadlock could arise, but it helps reduce the incidence.
Multi-core programming is hard .
I'll keep you posted!
Kind regards, Samuel Lourenço
Finally did some testing with the P1, and concluded that the code without lockset() and lockclr() is consistently faster. To test it, I've used two of my dev boards, Prop and Prop II. Also I've tested two different programs, one for each board. Note that the original Prop board runs at 64MHz, while the Prop II runs at 96MHz. I've ran the tests calculating all the prime numbers from 1 to 1000000.
Here are the results:
- Prop with older algorithm: 7:03.5 with locks, 6:52.4 without locks
- Prop II with newer algorithm: 4:40.6 with locks, 4:33.0 without locks
As you can notice, the improvement follows a similar ration on both cases. This is similar to what was observed during the tests with the P2. Thus, the results with the P2 make sense.
I wanted to mention that my previous conclusion was wrong, sinve I've noticed that I was running the program without locks using the CMM memory model, which is slower. That drove my to the wrong assumption that a program without locks would be slower on the P1.
Thanks, ersmith. I think the code is valid. I'll do more testing to see if results are consistent for big numbers.
P.S.: Attached is one of the programs that were used. The code has all lockset() and lockclr() operations removed, even for writing, since the cogs 1 to 7 write to different spaces in memory. Thus, lockset() and lockclr() are not needed at all (even for flags@i@, a variable that is also written by cog 0, but that in any case is always verified first and therefore never written simultaneously by different cogs). The code can be further optimized.
Kind regards, Samuel Lourenço