Note that there are some explanatory texts on larger screens.

plurals
  1. POcmpxchg for WORD faster than for BYTE
    primarykey
    data
    text
    <p>Yesterday I posted <a href="https://stackoverflow.com/questions/11959374/fastest-inline-assembly-spinlock">this question</a> on how to write a fast spinlock. Thanks to Cory Nelson I seem to have found a method which outperforms the other methods discussed in my question. I use the <code>CMPXCHG</code> instruction to check if the lock is 0 and thereby free. <code>CMPXCHG</code> operates on ´BYTE´, <code>WORD</code> and <code>DWORD</code>. I would assume that the instruction would operate faster on <code>BYTE</code>. But I wrote a lock implementing each of the datatypes:</p> <pre><code>inline void spin_lock_8(char* lck) { __asm { mov ebx, lck ;move lck pointer into ebx xor cl, cl ;set CL to 0 inc cl ;increment CL to 1 pause ; spin_loop: xor al, al ;set AL to 0 lock cmpxchg byte ptr [ebx], cl ;compare AL to CL. If equal ZF is set and CL is loaded into address pointed to by ebx jnz spin_loop ;jump to spin_loop if ZF } } inline void spin_lock_16(short* lck) { __asm { mov ebx, lck xor cx, cx inc cx pause spin_loop: xor ax, ax lock cmpxchg word ptr [ebx], cx jnz spin_loop } } inline void spin_lock_32(int* lck) { __asm { mov ebx, lck xor ecx, ecx inc ecx pause spin_loop: xor eax, eax lock cmpxchg dword ptr [ebx], ecx jnz spin_loop } } inline spin_unlock(&lt;anyType&gt;* lck) { __asm { mov ebx, lck mov &lt;byte/word/dword&gt; ptr [ebx], 0 } } </code></pre> <p>The lock was then tested using the following pseudo-code (please note that the lcm-pointer always will point to an address dividable by 4):</p> <pre><code>&lt;int/short/char&gt;* lck; threadFunc() { loop 10,000,000 times { spin_lock_8/16/32 (lck); spin_unlock(lck); } } main() { lck = (char/short/int*)_aligned_malloc(4, 4);//Ensures memory alignment start 1 thread running threadFunc and measure time; start 2 threads running threadFunc and measure time; start 4 threads running threadFunc and measure time; _aligned_free(lck); } </code></pre> <p>I've gotten the following results measured in msecs on a processor with 2 physical cores able to run 4 threads (Ivy Bridge).</p> <pre><code> 1 thread 2 threads 4 threads 8-bit 200 700 3200 16-bit 200 500 1400 32-bit 200 900 3400 </code></pre> <p>The data suggests that all functions take an equal amount of time to execute. But when multiple threads have to check if <code>lck == 0</code> using a 16-bit can be significantly faster. Why is that? I do not suppose it has something to do with the alignment of the <code>lck</code>?</p> <p>Thanks in advance.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload