如何使用C中的pthreads减少线程完成时屏障的数量

时间:2022-02-01 21:01:36

I have a function: createrWorkerPool which will spawn "n" worker threads and each of them will take input as file specified in the args for pthread_create, read the file modify a shared variable by using a mutex around it and wait at a barrier until all threads have done modifying their shared variable. This operation happens in a loop a large number of times.

我有一个函数:createrWorkerPool,它将生成“n”个工作线程,每个都将输入作为pthread_create的args中指定的文件,读取文件通过使用它周围的互斥锁修改共享变量并等待屏障直到所有线程已完成修改其共享变量。此操作在循环中发生很多次。

The problem I am facing is that lets consider there are two files file1 and file2 and file2 is much bigger in size than file1. The barrier synchronization works till completion of file1- but since it finishes execution it no longer reaches the barrier and file2 is stuck in the barrier forever.

我面临的问题是让我们考虑有两个文件file1和file2,file2的大小比file1大得多。屏障同步一直工作到文件1完成,但由于它完成执行,它不再到达屏障,文件2永远停留在屏障中。

My question is that is there a way to dynamically change the count of the number of threads the barrier is waiting on when a thread exits. so in the above case if file1 finishes early it decrements the barrier count from 2 to 1 so file1 can proceed with its execution. I tried looking at the man page but don't see any function.Example code

我的问题是,有一种方法可以动态更改屏障退出时屏障等待的线程数。所以在上面的例子中,如果file1提前完成,它会将屏障数从2递减到1,因此file1可以继续执行。我试着查看手册页,但没有看到任何函数。示例代码

pthread_mutex_t m1;
pthread_barrier_t b1;
//common function executed by each worker thread
void* doWork(void* arg) {
    const char* file = arg;
    while(1) {
        pthread_mutex_lock(&m1);
        // Modify shared variable
        pthread_mutex_unlock(&m1);
        // Wait for all threads to finish modifying shared variable
        pthread_barrier_wait(&b1);
        // Once all threads reach barrier check state of shared variable and do some task based on state
        // check for condition if true break out of loop

    }
    return 0;
}

So basically thread1 manipulating file1 finishes before and thread2 is stuck at the barrier forever

所以基本上thread1操作file1之前完成,而thread2永远停留在屏障上

1 个解决方案

#1


2  

You can't really change the barrier count while the barrier is in use like that.

当屏障像这样使用时,你无法真正改变屏障数量。

Presumably the problem is that the condition that is tested to break out of the loop is not true for all files at the same time - ie, each thread might execute a different number of loops.

据推测,问题是被测试突破循环的条件对于所有文件同时不是这样 - 即,每个线程可能执行不同数量的循环。

If this is the case, one solution is to have each thread that finishes early continue to loop around, but do nothing but wait on the barrier in each loop. Then arrange for the threads to all exit together - something like this:

如果是这种情况,一种解决方案是让每个早期完成的线程继续循环,但除了在每个循环中等待屏障之外什么都不做。然后安排线程一起退出 - 像这样:

void* doWork(void* arg)
{
    const char* file = arg;
    int work_done = 0;

    while(1) {
        if (work_done)
        {
            if (all_threads_done)
                break;

            pthread_barrier_wait(&b1);
            continue;
        }

        pthread_mutex_lock(&m1);
        // Modify shared variable
        pthread_mutex_unlock(&m1);
        // Wait for all threads to finish modifying shared variable
        pthread_barrier_wait(&b1);
        // Once all threads reach barrier check state of shared variable and do some task based on state
        if (finish_condition)
            work_done = 1;
    }
    return 0;
}

#1


2  

You can't really change the barrier count while the barrier is in use like that.

当屏障像这样使用时,你无法真正改变屏障数量。

Presumably the problem is that the condition that is tested to break out of the loop is not true for all files at the same time - ie, each thread might execute a different number of loops.

据推测,问题是被测试突破循环的条件对于所有文件同时不是这样 - 即,每个线程可能执行不同数量的循环。

If this is the case, one solution is to have each thread that finishes early continue to loop around, but do nothing but wait on the barrier in each loop. Then arrange for the threads to all exit together - something like this:

如果是这种情况,一种解决方案是让每个早期完成的线程继续循环,但除了在每个循环中等待屏障之外什么都不做。然后安排线程一起退出 - 像这样:

void* doWork(void* arg)
{
    const char* file = arg;
    int work_done = 0;

    while(1) {
        if (work_done)
        {
            if (all_threads_done)
                break;

            pthread_barrier_wait(&b1);
            continue;
        }

        pthread_mutex_lock(&m1);
        // Modify shared variable
        pthread_mutex_unlock(&m1);
        // Wait for all threads to finish modifying shared variable
        pthread_barrier_wait(&b1);
        // Once all threads reach barrier check state of shared variable and do some task based on state
        if (finish_condition)
            work_done = 1;
    }
    return 0;
}