為什么每個執行緒的時間總是相等的,所有執行緒都執行相同的指令?
我已經設定了一個程式來測量執行緒執行某個操作所需的時間(有關詳細資訊,請參見下文)。我的 MacBook 有 4 個物理內核或 8 個邏輯內核(可用超執行緒),所以我假設我最多可以并行運行 8 個執行緒。
我希望作業系統可以并行運行多達 8 個執行緒,并且一旦完成,就運行剩余的執行緒。但是,與這些預期相反,似乎所有執行緒(無論有多少)似乎總是花費相同的時間。為什么作業系統會這樣拆分它們,為什么它啟動所有執行緒而不是先完成前 8 個執行緒?為什么它會嘗試“并行”運行所有這些(我知道它實際上不能并行運行超過 8 個)?
另見下表;每個條形代表n 個執行緒的平均時間,n從 1 到 17。令人驚訝的是,平均時間等于每個執行緒的時間(這就是我覺得奇怪/不明白的地方 - 為什么它們都花費相同的時間? ):

這是我使用的一段代碼:
#include <stdio.h>
#include <sys/time.h>
#include <pthread.h>
#define MAX 1000000000
void * calculate (void * val) {
/* only time measurement ... */
long a = 0, start, end;
struct timeval timecheck;
gettimeofday(&timecheck, NULL);
start = (long)timecheck.tv_sec * 1000 (long)timecheck.tv_usec / 1000;
/* actual calculation (just for testing) */
for (unsigned i = 1; i <= MAX; i)
a = i;
gettimeofday(&timecheck, NULL);
end = (long)timecheck.tv_sec * 1000 (long)timecheck.tv_usec / 1000;
printf("%ld; time: %ldms\n", a, (end - start));
return NULL;
}
void main (int argc, char ** argv) {
pthread_t thread_1, thread_2, thread_3, thread_4; /* thread_5, ...*/
long a = 0, start, end;
struct timeval timecheck;
gettimeofday(&timecheck, NULL);
start = (long)timecheck.tv_sec * 1000 (long)timecheck.tv_usec / 1000;
if (pthread_create(&thread_1, NULL, &calculate, NULL) != 0)
perror("Couldn't create thread 1");
/* ... repeat the above two lines for each thread ... */
pthread_join(thread_1, NULL);
/* ... repeat the line above for each thread ... */
gettimeofday(&timecheck, NULL);
end = (long)timecheck.tv_sec * 1000 (long)timecheck.tv_usec / 1000;
printf("total time: %ldms\n", (end - start));
}
uj5u.com熱心網友回復:
為什么它啟動所有執行緒而不是先完成前 8 個執行緒?
您要求它創建并啟動 17 個執行緒。所以它創建并啟動了 17 個執行緒。
它無法知道在安排其他人之前運行 8 到完成是安全的。它甚至更不知道這將是有益的。(想象一下,如果執行緒大部分時間都被阻塞了。)但最重要的是,它甚至不知道執行緒是否會完成!
也許您想使用執行緒池模型,在這種模型中,您可以從共享佇列中獲取有限數量的執行緒。
執行緒池示例(C 語言)
執行緒池示例(在 Perl 中):
use threads;
use Thread::Queue qw( );
use constant NUM_WORKERS => 10;
sub work {
my $job = shift;
...
}
my $q = Thread::Queue->new(); # A thread-safe queue.
# Create worker threads.
my @threads;
for (1..NUM_WORKERS) {
push @threads, async {
while ( defined( my $job = $q->dequeue() ) ) {
work($job);
}
};
}
# Feed them work
for my $job (...) {
$q->enqueue($job);
}
# $q->dequeue normally blocks when the queue is empty.
# This causes it to return an undef value instead.
$q->end();
# Wait for the workers to complete the work.
$_->join() for @threads;
C 有執行緒池庫。(就此而言,Perl 也有。)
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/405185.html
標籤:
