【问题标题】:Atomic operation seems slower than Semaphore operations in multithreading shared process多线程共享进程中的原子操作似乎比信号量操作慢
【发布时间】:2017-11-10 14:54:45
【问题描述】:

您能想出为什么原子操作看起来比信号量慢的任何充分理由吗?即使指令减少了?

示例代码:

 void increment(){
     if (strcmp(type, "ATOMIC") == 0) {
         for (int i = 0; i < RUN_TIME; ++i) {
            atomic_fetch_add_explicit(&count, 1, memory_order_relaxed);
        }
    }
     if (strcmp(type, "SEMAPHORE") == 0){
        for (int i = 0; i < RUN_TIME; ++i) {
            sem_wait(sem);
            count++;
            sem_post(sem);
        }
    }
}

输出:

   time ./CMAIN "SEMAPHORE";time ./CMAIN "ATOMIC";
 [C] SEMAPHORE, count 4000000

 real    0m0.039s
 user    0m0.029s
 sys     0m0.002s
[C] ATOMIC, count 4000000

 real    0m0.092s
 user    0m0.236s
 sys     0m0.003s

【问题讨论】:

  • 您是否尝试过实际的多线程应用程序?这看起来像是在执行串行操作,因此没有资源争用,信号量也不必等待。
  • 如果不给我们编译器和平台,你只能期待一些挥之不去的推测性答案。
  • '减少指令'。你的意思是更少的c代码行?那完全无关紧要。
  • 真的吗?如果更多指令被推入流水线,从而产生更高的总延迟,这无关紧要吗?

标签: c multithreading semaphore atomic operations


【解决方案1】:

无法复制。对于 10^9 次迭代,我得到了(来自 bash、i5、x86_64、Linux):

$ TIMEFORMAT="%RR %UU %SS"
$ gcc atomic.c -Os -lpthread && ( time ./a.out ATOMIC  ; time ./a.out  SEMAPHORE )
1.572R  1.568U  0.000S  #ATOMIC
5.542R  5.536U  0.000S  #SEMAPHORE

(大约 4000000 次迭代的相同比率。)

我的 atomic.c (您的示例中已填入空格):

#include <stdio.h>
#include <string.h>
#include <stdatomic.h>
#include <semaphore.h>
#define RUN_TIME 100000000
char * type;
sem_t *sem;

_Atomic int count = ATOMIC_VAR_INIT(0);

 void increment(){
     if (strcmp(type, "ATOMIC") == 0) {
         for (int i = 0; i < RUN_TIME; ++i) {
            atomic_fetch_add_explicit(&count, 1, memory_order_relaxed);
        }
    }
     if (strcmp(type, "SEMAPHORE") == 0){
        for (int i = 0; i < RUN_TIME; ++i) {
            sem_wait(sem);
            count++;
            sem_post(sem);
        }
    }
}

int main(int C, char**V)
{
    sem_t s;
    sem_init(&s, 0, 1);
    sem = &s;
    type = V[1];
    increment();
}

请发布mcve,并附上您的平台规格。

【讨论】:

    【解决方案2】:

    这不应该是因为我读到的是“在信号量中,当某些进程试图访问不可用的信号量时,信号量将进程置于等待队列(FIFO)并将任务置于睡眠状态 ,这比原子操作更耗时或 CPU 开销更大。

    通常原子操作会执行得更快,因为它会一起加载、更新和修改指令。但是原子操作是特定于 CPU 的,即 n++ 是否会在单指令 (INC) 中执行,总是不能保证。所以由 CPU 决定,可能是因为这个原因你得到这样的输出。

    我理解我写的,建议将不胜感激。

    【讨论】:

    • 不,在任何体面的实现中,只要您在“快速路径”上,信号量(以及互斥量和其他东西)不会比原子慢。然后只有在拥塞时才进入内核等待或类似的状态。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-26
    • 2013-02-13
    • 2013-06-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多