簡體   English   中英

C pthread分批運行

[英]C pthreads run in portions

我列出了1000-10000個職位。 它存儲在簡單的char數組中。 我需要盡快完成清單上的工作。

我想隨時運行10個線程。 在上一個線程完成后,我如何立即(或幾乎立即)運行新線程?

#define THREADS_LIMIT 10
const char * const jobs[]= { "data1", .... }
...
for (i = 0; i < THREADS_LIMIT; ++i)
{
// run first 10 threads
}

完成上一個步驟后如何啟動線程? 我可以運行10個線程,然后等到所有線程完成后再運行下一個10。但是有沒有更有效的方法?

不要停止任何線程。 只需讓每個線程移至下一個作業,而不是銷毀它並創建一個新作業; 當沒有更多工作要做時,它們終止。 現在,您的主例程僅啟動THREAD_LIMIT線程,然后pthread_join它們全部啟動。

您可能會考慮的一件事是擁有一個線程安全的作業隊列,每個線程都可以從該隊列中拉出工作,直到沒有剩余工作為止。 然后啟動,但是有許多線程合適,讓它們全部工作,直到沒有更多的工作為止。 就像是:

#define THREADS_LIMIT 10

static pthread_mutex_t job_mutex = PTHREAD_MUTEX_INITIALIZER;
static const char * const jobs[]= { "data1", .... };

char const* get_job(void) 
{
    pthread_mutex_lock( &job_mutex);

    static char const* next_job = jobs;
    static char const* jobs_end = jobs + (sizeof(jobs)/sizeof(jobs[0]));

    char const* result = NULL;

    if (next_job != jobs_end) {
        result = next_job++;
    }

    pthread_mutex_unlock( &job_mutex);

    return result;
}



...
for (i = 0; i < THREADS_LIMIT; ++i)
{
// run first 10 threads
}


void* thread_fun( void* arg)
{
    for (char const* my_job = get_job(); my_job != NULL; my_job = get_job()) {
        // work on the job *my_job
    }

    return 0;
}

請注意,如果您的作業占用大量CPU,則您可能應該將旋轉的作業數限制為計算機具有的CPU核心數。 不僅如此,他們還將爭奪CPU時間。

但是,如果您希望靈活地使作業隊列動態化(以便可以在線程正在執行作業時將作業添加到隊列中),那么復雜性就會增加。 為了保持添加/刪除邏輯線程的安全,它僅增長了一點。 但是,為了確保仍有線程可以處理作業隊列,它增長了很多。例如,您必須確保在沒有競爭條件的情況下您認為仍有一個或多個線程可以處理作業隊列。隊列,但是這些線程實際上即將結束而無需再次檢查作業隊列。 當然,您可以擴展作業的存儲方式,但又要付出一些代價,您可以擴展此方式,以便作業隊列中可以添加項目

您肯定要有一個線程池,而不希望為每個任務啟動和停止線程。

主要的設計問題是如何將任務分配到池中,可以使用諸如0mq之類的中間件程序包在調度程序和工作程序之間執行無鎖IPC來簡化此類事務。

如果作業列表是硬編碼的,那么您可以靜態分配工作負載,並說給每個線程一個索引到作業隊列中,並使它們迭代直到完成。

最好的方法(我認為)是創建一個保存作業的隊列,然后啟動十個線程,這些線程僅從隊列中讀取下一個作業並對其進行處理。

這具有最小化線程創建/銷毀開銷以及線程之間工作負載的自動平衡的優點。 我的意思是,獲得快速工作的線程會自動獲得更多工作。

然后,在這10,000個作業的末尾,放置10個關閉作業,這將導致工作線程退出,然后等待它們。

整個方案如下所示:

main thread:
    create a queue
    do ten times:
        start a worker thread
    do ten thousand times:
        add normal job to queue
    do ten times:
        add shutdown job to queue
    wait for all workers to finish
    exit

worker thread:
    while true:
        get job from queue
        if job is shutdown job:
            exit
        process job

顯然,需要使用互斥來保護對隊列的訪問,以避免出現競爭情況。


不過,您需要記住一件事。 如果任務是CPU密集型的,那么擁有更多線程(而不是可用執行單元)(CPU或內核或其他)將不會獲得任何真正的好處。

例如,如果您只有一個內核,那么執行所需操作的最快方法就是根本不使用線程。 在這樣的CPU密集型任務上使用線程實際上可能會更慢,因為這會引入任務切換的開銷。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM