Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/google-maps/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 显示进程切换快于线程切换的微基准;什么';怎么了?_C_Linux_Multithreading_Process_Benchmarking - Fatal编程技术网

C 显示进程切换快于线程切换的微基准;什么';怎么了?

C 显示进程切换快于线程切换的微基准;什么';怎么了?,c,linux,multithreading,process,benchmarking,C,Linux,Multithreading,Process,Benchmarking,我有两个简单的微基准试着测量线程和进程切换的开销,但是进程切换的开销比线程切换的开销要低,这是出乎意料的。设置:1.8GHz Core 2 Duo、2GB RAM、Linux 2.6.32-21通用x86_64(Ubuntu 10.04)。我得到: 每个过程开关约2.1-2.4us ~4us/线程开关 我还尝试使用numactl--physcpubind=0和likwid pin-c0运行,但这似乎只会减慢线程切换到5us的速度。有人知道评估有什么问题,或者这些结果是否正确,为什么 代码位于

我有两个简单的微基准试着测量线程和进程切换的开销,但是进程切换的开销比线程切换的开销要低,这是出乎意料的。设置:1.8GHz Core 2 Duo、2GB RAM、Linux 2.6.32-21通用x86_64(Ubuntu 10.04)。我得到:

  • 每个过程开关约2.1-2.4us
  • ~4us/线程开关
我还尝试使用
numactl--physcpubind=0
likwid pin-c0
运行,但这似乎只会减慢线程切换到5us的速度。有人知道评估有什么问题,或者这些结果是否正确,为什么

代码位于下面的URL,r1667粘贴在此处:

//在zs上,~2.1-2.4us/switch
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
uint32_t计数器;
pthread_mutex_t LOCK;
pthread_mutex_t START;
sem_t*s0、*s1、*s2;
无效*线程(
无效*未使用
) {
//等我们开火吧
sem_-wait(s2);
对于(;;){
pthread_mutex_lock(&lock);
pthread_mutex_unlock(&LOCK);
计数器++;
sem_岗位(s0);
sem_-wait(s1);
}
返回0;
}
int64_t timeInMS()
{
结构时间值t;
gettimeofday(&t,NULL);
返回(
(int64_t)t.tv_sec*1000+
(int64_t)t.tv_usec/1000
);
}
int main(
int argc,
字符**argv
) {
int64_t启动;
pthread_t t1;
pthread_mutex_init(&LOCK,NULL);
计数器=0;
s0=sem_open(“/s0”,O_CREAT,0022,0);
如果(s0==0){perror(“sem_open”);退出(1)}
s1=sem_open(“/s1”,O_CREAT,0022,0);
如果(s1==0){perror(“sem_open”);退出(1)}
s2=sem_open(“/s2”,O_CREAT,0022,0);
如果(s2==0){perror(“sem_open”);退出(1)}
int x,y,z;
sem_getvalue(s0和x);
sem_getvalue(s1和y);
sem_getvalue(s2和z);
printf(“%d%d%d\n”,x,y,z);
pid_t pid=fork();
如果(pid){
pthread_create(&t1,NULL,threads,NULL);
pthread_detach(t1);
//获得开始时间并开火
start=timeInMS();
sem_岗位(s2);
sem_岗位(s2);
//等一下
睡眠(1);
//停止线程
pthread_mutex_lock(&lock);
//看看到底过了多少时间。睡眠不能保证这一点
//我只睡了一秒钟,我可能会睡得更久,因为即使是在睡觉之后
//醒来后,可能需要一些时间才能恢复CPU时间。进一步
//在我拿到锁之前,可能还要过一段时间!
int64_t time=timeInMS()-开始;
//相应地更正线程开关的数量
计数器=(uint32_t)((uint64_t)计数器*2*1000)/时间;
printf(“大约一秒钟内的过程开关数量为%u\n”,计数器);
printf(“每个开关大约%f微秒”,1000000.0/计数器);
//清理
杀死(pid,9);
等待(0);
sem_关闭(s0);
sem_-close(s1);
sem_取消链接(“/s0”);
sem_取消链接(“/s1”);
sem_取消链接(“/s2”);
}否则{
如果(1){sem_t*t=s0;s0=s1;s1=t;}
线程(0);//永不返回
}
返回0;
}

//来自
//在zs上,约4-5us/开关;尝试使计数器仅由一个线程更新,但没有差异
#包括
#包括
#包括
#包括
#包括
#包括
uint32_t计数器;
pthread_mutex_t LOCK;
pthread_mutex_t START;
p线程条件;
无效*线程(
无效*未使用
) {
//等我们开火吧
pthread_mutex_lock(&START);
pthread_mutex_unlock(&START);
int first=1;
pthread_mutex_lock(&lock);
//如果我不是第一个线程,那么另一个线程已经在等待了
//条件,因此我必须先唤醒它,否则我们会死锁
如果(计数器>0){
pthread_cond_信号(&CONDITION);
第一个=0;
}
对于(;;){
如果(第一个)计数器++;
pthread_cond_wait(&CONDITION,&LOCK);
//总是在处理前唤醒另一个线程。另一个
//只要我不去,线程就不能做任何事情
//先回去睡觉。
pthread_cond_信号(&CONDITION);
}
pthread_mutex_unlock(&LOCK);
返回0;
}
int64_t timeInMS()
{
结构时间值t;
gettimeofday(&t,NULL);
返回(
(int64_t)t.tv_sec*1000+
(int64_t)t.tv_usec/1000
);
}
int main(
int argc,
字符**argv
) {
int64_t启动;
pthread_t t1;
pthread_t t2;
pthread_mutex_init(&LOCK,NULL);
pthread_mutex_init(&START,NULL);
pthread_cond_init(&CONDITION,NULL);
pthread_mutex_lock(&START);
计数器=0;
pthread_create(&t1,NULL,threads,NULL);
pthread_create(&t2,NULL,threads,NULL);
pthread_detach(t1);
pthread_detach(t2);
//获得开始时间并开火
start=timeInMS();
pthread_mutex_unlock(&START);
//等一下
睡眠(1);
//停止两个线程
pthread_mutex_lock(&lock);
//看看到底过了多少时间。睡眠不能保证这一点
//我只睡了一秒钟,我可能会睡得更久,因为即使是在睡觉之后
//醒来后,可能需要一些时间才能恢复CPU时间。进一步
//在我拿到锁之前,可能还要过一段时间!
int64_t time=timeInMS()-开始;
//相应地更正线程开关的数量
计数器=(uint32_t)((uint64_t)计数器*2*1000)/时间;
printf(“大约一秒钟内线程开关的数量为%u\n”,计数器);
printf(“每个开关大约%f微秒”,1000000.0/计数器);
返回0;
}
很简单:pthread_mutex_lock()在您的系统上大约需要2ms,线程版本在循环中每次需要两个锁,而进程版本只需要一个锁。

历史上,Unix(及其派生的Linux)拥有相对便宜的
fork()
// on zs, ~2.1-2.4us/switch

#include <stdlib.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <semaphore.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/time.h>
#include <pthread.h>

uint32_t COUNTER;
pthread_mutex_t LOCK;
pthread_mutex_t START;
sem_t *s0, *s1, *s2;

void * threads (
    void * unused
) {
    // Wait till we may fire away
    sem_wait(s2);

    for (;;) {
        pthread_mutex_lock(&LOCK);
        pthread_mutex_unlock(&LOCK);
        COUNTER++;
        sem_post(s0);
        sem_wait(s1);
    }
    return 0;
}

int64_t timeInMS ()
{
    struct timeval t;

    gettimeofday(&t, NULL);
    return (
        (int64_t)t.tv_sec * 1000 +
        (int64_t)t.tv_usec / 1000
    );
}

int main (
    int argc,
    char ** argv
) {
    int64_t start;
    pthread_t t1;

    pthread_mutex_init(&LOCK, NULL);

    COUNTER = 0;
    s0 = sem_open("/s0", O_CREAT, 0022, 0);
    if (s0 == 0) { perror("sem_open"); exit(1); }
    s1 = sem_open("/s1", O_CREAT, 0022, 0);
    if (s1 == 0) { perror("sem_open"); exit(1); }
    s2 = sem_open("/s2", O_CREAT, 0022, 0);
    if (s2 == 0) { perror("sem_open"); exit(1); }

    int x, y, z;
    sem_getvalue(s0, &x);
    sem_getvalue(s1, &y);
    sem_getvalue(s2, &z);
    printf("%d %d %d\n", x, y, z);

    pid_t pid = fork();
    if (pid) {
      pthread_create(&t1, NULL, threads, NULL);
      pthread_detach(t1);
      // Get start time and fire away
      start = timeInMS();
      sem_post(s2);
      sem_post(s2);

      // Wait for about a second
      sleep(1);
      // Stop thread
      pthread_mutex_lock(&LOCK);

      // Find out how much time has really passed. sleep won't guarantee me that
      // I sleep exactly one second, I might sleep longer since even after being
      // woken up, it can take some time before I gain back CPU time. Further
      // some more time might have passed before I obtained the lock!
      int64_t time = timeInMS() - start;
      // Correct the number of thread switches accordingly
      COUNTER = (uint32_t)(((uint64_t)COUNTER * 2 * 1000) / time);
      printf("Number of process switches in about one second was %u\n", COUNTER);
      printf("roughly %f microseconds per switch\n", 1000000.0 / COUNTER);

      // clean up
      kill(pid, 9);
      wait(0);
      sem_close(s0);
      sem_close(s1);
      sem_unlink("/s0");
      sem_unlink("/s1");
      sem_unlink("/s2");
    } else {
      if (1) { sem_t *t = s0; s0 = s1; s1 = t; }
      threads(0); // never return
    }
    return 0;
}
// From <http://stackoverflow.com/questions/304752/how-to-estimate-the-thread-context-switching-overhead>

// on zs, ~4-5us/switch; tried making COUNTER updated only by one thread, but no difference

#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/time.h>

uint32_t COUNTER;
pthread_mutex_t LOCK;
pthread_mutex_t START;
pthread_cond_t CONDITION;

void * threads (
    void * unused
) {
    // Wait till we may fire away
    pthread_mutex_lock(&START);
    pthread_mutex_unlock(&START);
    int first=1;

    pthread_mutex_lock(&LOCK);
    // If I'm not the first thread, the other thread is already waiting on
    // the condition, thus Ihave to wake it up first, otherwise we'll deadlock
    if (COUNTER > 0) {
        pthread_cond_signal(&CONDITION);
        first=0;
    }
    for (;;) {
        if (first) COUNTER++;
        pthread_cond_wait(&CONDITION, &LOCK);
        // Always wake up the other thread before processing. The other
        // thread will not be able to do anything as long as I don't go
        // back to sleep first.
        pthread_cond_signal(&CONDITION);
    }
    pthread_mutex_unlock(&LOCK);
    return 0;
}

int64_t timeInMS ()
{
    struct timeval t;

    gettimeofday(&t, NULL);
    return (
        (int64_t)t.tv_sec * 1000 +
        (int64_t)t.tv_usec / 1000
    );
}


int main (
    int argc,
    char ** argv
) {
    int64_t start;
    pthread_t t1;
    pthread_t t2;

    pthread_mutex_init(&LOCK, NULL);
    pthread_mutex_init(&START, NULL);   
    pthread_cond_init(&CONDITION, NULL);

    pthread_mutex_lock(&START);
    COUNTER = 0;
    pthread_create(&t1, NULL, threads, NULL);
    pthread_create(&t2, NULL, threads, NULL);
    pthread_detach(t1);
    pthread_detach(t2);
    // Get start time and fire away
    start = timeInMS();
    pthread_mutex_unlock(&START);
    // Wait for about a second
    sleep(1);
    // Stop both threads
    pthread_mutex_lock(&LOCK);
    // Find out how much time has really passed. sleep won't guarantee me that
    // I sleep exactly one second, I might sleep longer since even after being
    // woken up, it can take some time before I gain back CPU time. Further
    // some more time might have passed before I obtained the lock!
    int64_t time = timeInMS() - start;
    // Correct the number of thread switches accordingly
    COUNTER = (uint32_t)(((uint64_t)COUNTER * 2 * 1000) / time);
    printf("Number of thread switches in about one second was %u\n", COUNTER);
    printf("roughly %f microseconds per switch\n", 1000000.0 / COUNTER);
    return 0;
}