我寫了四個不同的程序來計算兩個文件中的總詞數。這四個版本看起來大致相同。前三個版本使用兩個線程進行計數,而只有三個語句的順序不同。最後一個版本使用一個線程來計數。我將首先列出每個版本的不同部分和公共部分,然後列出每個版本的輸出和我的問題。pthread程序中例程的額外執行時間是多少?
不同的部分:
// version 1
count_words(&file1);
pthread_create(&new_thread, NULL, count_words, &file2);
pthread_join(new_thread, NULL);
// version 2
pthread_create(&new_thread, NULL, count_words, &file2);
count_words(&file1);
pthread_join(new_thread, NULL);
// version 3
pthread_create(&new_thread, NULL, count_words, &file2);
pthread_join(new_thread, NULL);
count_words(&file1);
// version 4
count_words(&file1);
count_words(&file2);
公共部分:(插入不同的部分爲這個共同的部分,使完整版)
#include <stdio.h>
#include <pthread.h>
#include <ctype.h>
#include <stdlib.h>
#include <time.h>
#define N 2000
typedef struct file_t {
char *name;
int words;
} file_t;
double time_diff(struct timespec *, struct timespec *);
void *count_words(void *);
// Usage: progname file1 file2
int main(int argc, char *argv[]) {
pthread_t new_thread;
file_t file1, file2;
file1.name = argv[1];
file1.words = 0;
file2.name= argv[2];
file2.words = 0;
// Insert different part here
printf("Total words: %d\n", file1.words+file2.words);
return 0;
}
void *count_words(void *arg) {
FILE *fp;
file_t *file = (file_t *)arg;
int i, c, prevc = '\0';
struct timespec process_beg, process_end;
struct timespec thread_beg, thread_end;
double process_diff, thread_diff;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &process_beg);
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &thread_beg);
fp = fopen(file->name, "r");
for (i = 0; i < N; i++) {
while ((c = getc(fp)) != EOF) {
if (!isalnum(c) && isalnum(prevc))
file->words++;
prevc = c;
}
fseek(fp, 0, SEEK_SET);
}
fclose(fp);
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &process_end);
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &thread_end);
process_diff = time_diff(&process_beg, &process_end);
thread_diff = time_diff(&thread_beg, &thread_end);
printf("count_words() in %s takes %.3fs process time and"
"%.3fs thread time\n", file->name, process_diff, thread_diff);
return NULL;
}
double time_diff(struct timespec *beg, struct timespec *end) {
return ((double)end->tv_sec + (double)end->tv_nsec*1.0e-9)
- ((double)beg->tv_sec + (double)beg->tv_nsec*1.0e-9);
}
注意
- 文件1中一個包含10000字「單詞」的文件。 file2是由cp命令創建的file1的副本。
- 爲了使執行時間足夠長,程序會重複計數單詞。 N是循環的數量。所以結果不是準確的總字數,而是乘以N.
- 請不要過分強調計數算法。我只關心這個例子中的執行時間。
- 重要信息:該機器是Intel®Celeron®CPU 420 @ 1.60GHz。一個核心。操作系統是Linux 3.2.0。也許一個核心是像其他人所說的這種奇怪現象的原因。但我仍然想弄明白。
該程序對字進行計數並使用clock_gettime()來計算進程cpu時間和例程count_words()的線程cpu時間,然後輸出時間和字數。以下是輸出和我對問題的評論。如果有人能夠解釋什麼是額外的時間,我將非常感激。
// version 1
count_words() in file1 takes 2.563s process time and 2.563s thread time
count_words() in file2 takes 8.374s process time and 8.374s thread time
Total words: 40000000
評論:原始線程完成count_words()並等待新線程死亡。當在新線程中運行count_words()時,不會發生上下文切換(因爲進程時間==線程時間)。 爲什麼需要這麼多時間? count_words()在新線程中會發生什麼?
// version 2
count_words() in file1 takes 16.755s process time and 8.377s thread time
count_words() in file2 takes 16.753s process time and 8.380s thread time
Total words: 40000000
點評:這裏有兩個線程並行運行。發生上下文切換,所以進程時間>線程時間。
// version 3
count_words() in file2 takes 8.374s process time and 8.374s thread time
count_words() in file1 takes 8.365s process time and 8.365s thread time
Total words: 40000000
評論:新線程首先計數,原始線程等待它。新線程加入後,原始線程開始計數。 它們都沒有上下文切換,爲什麼要花費很多時間,特別是新線程加入後的計數?
// version 4
count_words() in file1 takes 2.555s process time and 2.555s thread time
count_words() in file2 takes 2.556s process time and 2.556s thread time
Total words: 40000000
點評:最快的版本。沒有創建新的線程。兩個count_words()都在一個線程中運行。
引用版本1 + 2:虛假共享?也許這有助於:http://stackoverflow.com/q/8331255/694576 – alk 2013-04-08 11:55:40
@alk:我的機器有一個核心。正如你引用的鏈接中接受的答案所說,虛假分享是多核心的結果。單核可能發生嗎? – 2013-04-09 03:29:06