2015-07-24 5 views
0

я просто "ускорен" кусочек этого кода:Насколько дороги pthread_rwlock_ *?

double value = ComputeSomething(point); 

по существу, как это:

double value; 
pthread_rwlock_rdlock(& m_Mutex); 
if(! SmallCache.Find(point, & value)) { 
    pthread_rwlock_unlock(& m_Mutex); 
    double value = ComputeSomething(point); 
    pthread_rwlock_wrlock(& m_Mutex); 
    SmallCache.Add(point, value); 
} 
pthread_rwlock_unlock(& m_Mutex); 
return value; 

кэш около 75%. Кэш - это std::list; SmallCache.Find пересекает его от begin до end. SmallCache.Add делает push_front новых значений и pop_back старых, чтобы сохранить список довольно маленьким, всего 16 единиц. ComputeSomething считается умеренно дорогим.

Результат этого ускорения (барабанный бой) 5% -ный спад.

Таким образом, вопросы: что может быть причиной вышеупомянутого замедления? Я подозреваю pthread_rwlock_*, хотя и не уверен. Если замедление было действительно связано с блокировкой, как можно избежать этого?

+0

В зависимости от архитектуры, и, конечно же, «Как много споров на замок», - другими словами, он не может быть сам ЗАМОК (звонки для блокировки/разблокировки) , но тот факт, что ваши потоки ждут освобождения блокировки ... –

+2

И относительная стоимость вычисления против чеканки 16 указателей (и выделение кучи при пропуске кеша). –

+1

Я бы, вероятно, сделал его либо массивом, либо вектором вместо списка ...;) –

ответ

0

Так, глядя на разборки pthread_rwlock_rdlock и pthread_rwlock_wrlock, это достаточно легкий в «быстром случае» (то есть, нет никакого раздора, мы можем взять замок без труда) - о 20 инструкций - один из которых - cmpxchg (так что попросите любого другого процессора «освободить эту строку кеша»), но все остальное - довольно простые/легкие инструкции.

Конечно, если вам нужно подождать, то вам предстоит немного поехать, но это то, чего вы ожидаете.

[И нет, не спрашивайте меня, как именно он работает]

Ниже приведен код для rdlock, но wrlock очень похожи по сложности.

код здесь:

406760: 48 89 fa    mov %rdi,%rdx 
    406763: 90      nop 
    406764: 0f b6 47 20    movzbl 0x20(%rdi),%eax 
    406768: 84 c0     test %al,%al 
    40676a: 0f 8e 90 00 00 00  jle 406800 <__pthread_rwlock_rdlock+0xa0> // May need to do stuff here 

    406770: 83 e8 01    sub $0x1,%eax 
    406773: 88 47 20    mov %al,0x20(%rdi) 
    406776: bf 01 00 00 00   mov $0x1,%edi 
    40677b: 31 c0     xor %eax,%eax 
    40677d: 8b 72 1c    mov 0x1c(%rdx),%esi 
    406780: f0 0f b1 3a    lock cmpxchg %edi,(%rdx) 
    406784: 74 16     je  40679c <__pthread_rwlock_rdlock+0x3c> 
<---- Lock maybe taken! 
Else wait... 
    406786: 48 8d 3a    lea (%rdx),%rdi 
    406789: 48 81 ec 80 00 00 00 sub $0x80,%rsp 
    406790: e8 bb 34 00 00   callq 409c50 <__lll_lock_wait> 
    406795: 48 81 c4 80 00 00 00 add $0x80,%rsp 

---> Maybe taken? 
    40679c: 8b 72 18    mov 0x18(%rdx),%esi 
    40679f: 85 f6     test %esi,%esi 
    4067a1: 75 4c     jne 4067ef <__pthread_rwlock_rdlock+0x8f> 
<---- Take slow path. 
Else may still have taken the lock. 
    4067a3: 8b 4a 14    mov 0x14(%rdx),%ecx 
    4067a6: 85 c9     test %ecx,%ecx 
    4067a8: 75 3e     jne 4067e8 <__pthread_rwlock_rdlock+0x88> 
<--- Nope, slow path 
    4067aa: 8b 4a 04    mov 0x4(%rdx),%ecx 
    4067ad: 8d 41 01    lea 0x1(%rcx),%eax 
    4067b0: 85 c0     test %eax,%eax 
    4067b2: 89 42 04    mov %eax,0x4(%rdx) 
    4067b5: 0f 84 d5 00 00 00  je  406890 <__pthread_rwlock_rdlock+0x130> 
<--- Slow path, lock not taken. 
    Else: Success, we have the lock, update number of times it's locked. 
    4067bb: 90      nop 
    4067bc: 45 31 c0    xor %r8d,%r8d 
    4067bf: 8b 72 1c    mov 0x1c(%rdx),%esi 
    4067c2: f0 ff 0a    lock decl (%rdx) 
    4067c5: 74 16     je  4067dd <__pthread_rwlock_rdlock+0x7d> 
<---- Lock been taken, return! 
ELSE if necessary, call the wake function too. 
    4067c7: 48 8d 3a    lea (%rdx),%rdi 
    4067ca: 48 81 ec 80 00 00 00 sub $0x80,%rsp 
    4067d1: e8 1a 35 00 00   callq 409cf0 <__lll_unlock_wake> 
    4067d6: 48 81 c4 80 00 00 00 add $0x80,%rsp 
--> We have the lock... 
    4067dd: 44 89 c0    mov %r8d,%eax 
    4067e0: c3      retq 
Смежные вопросы