c++ 如何实现线程的负载均衡?

k10s72fa  于 2022-12-24  发布在  其他
关注(0)|答案(1)|浏览(256)

我有一个关于如何在线程之间进行负载平衡的问题。每个线程应该处理N * N矩阵中的特定行,例如,如果N = 4且Num_Threads = 2。请注意,这种情况仅适用于(N % Num_Threads)== 0。

for (int i = 0 ; i < num_threads; i++){
    if ( i == 0) { RANGE -> R1 = 0; RANGE -> R2 = n/num_threads; }
    else {
        RANGE -> R1 = RANGE -> R2  ; // I have defined a struct previously contains R1,R2 which means Row1,Row2
        RANGE -> R2 = RANGE -> R1 + n/num_threads ; }
        cout << "ThreadID= " << i << ", startRow= " << RANGE -> R1 << ", endRow= " << RANGE -> R2 << endl ;   
        pthread_create(&threads[i],NULL,Median,RANGE);
    }
}

输出:

ThreadID= 0 start_row = 0  , end_row = 
ThreadID= 1 ..... = 2 , .....=4
    • 但是,如果(N % Num_Threads)!= 0且Num_Threads〈N,例如N = 5且Num_Threads = 3,我如何执行负载平衡。**

我已经尝试给每个线程(N/Num_threads)行,但我应该如何划分线程的剩余(N % Numthreads)行?
例如,如果N = 5,Num_threads = 3,那么将剩下2行,我如何将它们分布在3个线程上?如果是像N = 101和Num_Threads = 7这样的大数字,则将更难做到这一点,我不知道如何实现这一点。

  • 注意 *:不是所有线程都应该占用相同的行数,但是代码应该尝试在线程之间实现**尽可能多的负载平衡。
zd287kbt

zd287kbt1#

您已经拥有并正在使用一个对象来向每个线程传达它将操作的行的范围,所以我认为您所要求的只是如何计算这些范围,以便它们的大小彼此之间的差异不超过一项。
假设你有N个项目要分配到T个线程上。所有线程将得到至少N/T个项目,N%T个线程将分别得到一个以上的项目。有很多方法可以编写代码来实现这一点,但这一种方法非常清楚和简单:

size_t next_range_start = 0;

for (int i = 0 ; i < num_threads; i++) {
    size_t next_range_end_exclusive = next_range_start + n / num_threads;

    if (i < (n % num_threads)) {
        next_range_end_exclusive++;
    }

    cout << "ThreadID = " << i
         << ", startRow = " << next_range_start
         << ", endRow (exclusive) = " << next_range_end_exclusive
         << endl ;
    pthread_create(&threads[i], NULL, Median,
            new range_type(next_range_start, next_range_end_exclusive));
    next_range_start = next_range_end_exclusive;
}

请注意,要为不同的线程使用相同的range对象,您需要有足够的同步和信令,以确保在主线程使用下一个工作线程的值更新该对象之前,每个工作线程都读取了它所需要的数据。为每个线程使用单独的range对象要容易得多,如图所示。然而,它确实将释放它接收的范围对象的责任放在每个工作者线程上。
还要注意的是,上面假设range对象的结束索引是 exclusive,而不是inclusive。你的原始代码暗示了这一点,但有点模糊。也可以使用inclusive结束索引,但要做一些调整。

相关问题