スレッドスイッチオーバーヘッド時間を測定しようとしています。 私は2つのスレッド、共有変数、mutexロック、および2つの条件変数を持っています。 2つのスレッドは、共有変数に1または0のいずれかを書き込むために前後に切り替わります。これは、スレッドコンテキストスイッチのオーバーヘッドを測定する正しいソリューションですか?
私は、pthread_cond_wait(& cond、& mutex)の待機時間は、スレッドコンテキストの切り替え時間が2 xにほぼ等しいと仮定しています。スレッド1が条件変数を待たなければならない場合、thread2->スレッド2コンテキストスイッチ - > thread2はそのタスクを実行し、条件変数に最初のスレッドを起動するように信号を送ります。 - >コンテキストスイッチをスレッド1に戻す - > thread1がロックを再取得します。
私の前提は正しいですか?
私のコードは以下の通りです:
#include <sys/types.h>
#include <wait.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/resource.h>
#include <dirent.h>
#include <ctype.h>
#include<signal.h>
#include <stdio.h>
#include <stdint.h>
#include <time.h>
#include <pthread.h>
int var = 0;
int setToZero = 1;
int count = 5000;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t isZero = PTHREAD_COND_INITIALIZER;
pthread_cond_t isOne = PTHREAD_COND_INITIALIZER;
struct timespec firstStart;
unsigned long long timespecDiff(struct timespec *timeA_p, struct timespec *timeB_p)
{
return ((timeA_p->tv_sec * 1000000000) + timeA_p->tv_nsec) -
((timeB_p->tv_sec * 1000000000) + timeB_p->tv_nsec);
}
void* thread1(void* param)
{
int rc;
struct timespec previousStart;
struct timespec start; //start timestamp
struct timespec stop; //stop timestamp
unsigned long long result;
int idx = 0;
int measurements[count];
clock_gettime(CLOCK_MONOTONIC, &stop);
result = timespecDiff(&stop,&firstStart);
printf("first context-switch time:%llu\n", result);
clock_gettime(CLOCK_MONOTONIC, &previousStart);
while(count > 0){
//acquire lock
rc = pthread_mutex_lock(&mutex);
clock_gettime(CLOCK_MONOTONIC,&start);
while(setToZero){
pthread_cond_wait(&isOne,&mutex); // use condition variables so the threads don't busy wait inside local cache
}
clock_gettime(CLOCK_MONOTONIC,&stop);
var = 0;
count--;
setToZero = 1;
//printf("in thread1\n");
pthread_cond_signal(&isZero);
//end of critical section
rc = pthread_mutex_unlock(&mutex); //release lock
result = timespecDiff(&stop,&start);
measurements[idx] = result;
idx++;
}
result = 0;
int i = 0;
while(i < idx)
{
result += measurements[i++];
}
result = result /(2*idx);
printf("thread1 result: %llu\n",result);
}
void* thread2(void* param)
{
int rc;
struct timespec previousStart;
struct timespec start; //start timestamp
struct timespec stop; //stop timestamp
unsigned long long result;
int idx = 0;
int measurements[count];
while(count > 0){
//acquire lock
rc = pthread_mutex_lock(&mutex);
clock_gettime(CLOCK_MONOTONIC,&start);
while(!setToZero){
pthread_cond_wait(&isZero,&mutex);
}
clock_gettime(CLOCK_MONOTONIC,&stop);
var = 1;
count--;
setToZero = 0;
//printf("in thread2\n");
pthread_cond_signal(&isOne);
//end of critical section
rc = pthread_mutex_unlock(&mutex); //release lock
result = timespecDiff(&stop,&start);
measurements[idx] = result;
idx++;
}
result = 0;
int i = 0;
while(i < idx)
{
result += measurements[i++];
}
result = result /(2*idx);
printf("thread2 result: %llu\n",result);
}
int main(){
pthread_t threads[2];
pthread_attr_t attr;
pthread_attr_init(&attr);
clock_gettime(CLOCK_MONOTONIC,&firstStart);
pthread_create(&threads[0],&attr,thread1,NULL);
pthread_create(&threads[1],&attr,thread2,NULL);
printf("waiting...\n");
pthread_join(threads[0],NULL);
pthread_join(threads[1],NULL);
pthread_cond_destroy(&isOne);
pthread_cond_destroy(&isZero);
}
私は次の時間を得る:
first context-switch time:144240
thread1 result: 3660
thread2 result: 3770
CPUコアが1つしかない場合を除いて、スレッドはこの場合はコンテキスト切り替え*する必要はありません。 – EOF
私は単一のコアマシンを使用しています – JJTO
そして、そこには他のプロセス/スレッドがCPU時間を要求しているという事実があります。コンテキストスイッチは、状態変数のロード/アンロードなどです。私はあなたがそれを測定することはできないと思っています。あなたはオブザーバーの影響を受けるかもしれません:) OSはコンテキストスイッチから責任を負います。あなたのプロセスが眠っている間にすべてが起こります。 –