2017-02-15 9 views
1

スレッドスイッチオーバーヘッド時間を測定しようとしています。 私は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 
+0

CPUコアが1つしかない場合を除いて、スレッドはこの場合はコンテキスト切り替え*する必要はありません。 – EOF

+0

私は単一のコアマシンを使用しています – JJTO

+0

そして、そこには他のプロセス/スレッドがCPU時間を要求しているという事実があります。コンテキストスイッチは、状態変数のロード/アンロードなどです。私はあなたがそれを測定することはできないと思っています。あなたはオブザーバーの影響を受けるかもしれません:) OSはコンテキストスイッチから責任を負います。あなたのプロセスが眠っている間にすべてが起こります。 –

答えて

0

あなたが言う:

私は、(&ミューテックスを&指揮をpthread_cond_waitのを想定しています)待機時間は、スレッドコンテキストの切り替え時間の2倍にほぼ等しくなります。

これは有効な前提ではありません。 mutexが解放されると、これはカーネルに通知し、カーネルは他方のスレッドを起動させなければなりません。実行するのを待っている他のスレッドがある場合など、即座に実行することはできません。ミューテックスは、その名前が示すように、ものがでなければが起こることを保証します。いつの日かは保証されません。

プロセス内からコンテキストスイッチを確実に測定することはできません。確かにPosix APIを使用しないため、Posix APIを使用しないこともあります。 Linuxの

  • あなたは数えることができるコンテキストは/proc/[pid]/statusを使用して、プロセスまたはスレッドのために切り替わります。

  • Windowsでは、この情報はパフォーマンスモニタAPIから入手できます。

これらのいずれかがあなたの目標に向かってあなたを得るかどうかはわかりません。あなたが本当に知りたいのは、マルチスレッドシステムを使ってどれだけパフォーマンスに影響を与えるかということですが、アプリケーション全体のパフォーマンスを測定する必要があります。

関連する問題