【问题标题】:C - massive # of posix threads spinning out of control and no longer creating new onesC - 大量 posix 线程失去控制,不再创建新线程
【发布时间】:2010-12-22 16:21:38
【问题描述】:

我在课堂上有一个作业,要求我们使用 POSIX 线程并创建 n*(n-1)/2 个线程来处理包含 n 个元素的数据集。

您基本上可以将其视为概率中的经典“握手”。

我知道,对于大型数据集,它会使应用程序受 CPU 限制,最终它会花费大量时间进行上下文切换,这将是无用的,但任务要求我们这样做。

但是,我创建所有线程的循环会在一段时间后停止创建它们。

对于下面的代码,我会看到如下输出:

making thread
thread start
thread done
made thread 1944
making thread
thread start
thread done
made thread 1945
making thread
thread start
thread done
made thread 1946
making thread

一段时间后,我将不再看到“线程开始”和“线程完成”消息,而只会看到“正在创建线程,已创建线程”消息。

这是创建线程的循环:

    int tCtr = 0;
    tArr = (pthread_t*)malloc(((numbers_read) * (numbers_read - 1)/2) * sizeof(pthread_t));
    for(i=0; i<numbers_read; i++){
        int j;
        for(j=i; j<numbers_read; j++){
            // n(n-1)/2
            if(i != j){
                printf("making thread\n");
                struct comparison_struct *data;
                data = (struct comparison_struct *)malloc(sizeof(struct comparison_struct));
                data->i_value = &numbers[i];
                data->j_value = &numbers[j];
                data->i_arr_entry = &wArr[i];
                data->j_arr_entry = &wArr[j];
                pthread_create(&tArr[tCtr], NULL, compare_thread, (void *)data);
                printf("made thread %d\n", tCtr);
                tCtr++;
            }
        }
    }
    for(i=0; i<tCtr; i++){
        pthread_join(tArr[i], NULL);
    }
    free(tArr);

这里是包含线程代码的子程序:

void *compare_thread(void *vData) {
    printf("thread start\n");
    struct comparison_struct *data;
    data = (struct comparison_struct *)vData;
    if(*data->i_value <= *data->j_value){
        *data->i_arr_entry = 0;
    } else {
        *data->j_arr_entry = 0;
    }
    free(vData);
    printf("thread done\n");
    return NULL;
}

有人有什么想法吗?我是 pthreads 的新手,无法弄清楚。

我知道,如果我在 pthread_create 之后立即调用 pthread_join,则应用程序可以工作 - 但是它会阻塞每个线程,我认为这会降低性能,因为实际上一次只会运行 2 个线程.

【问题讨论】:

  • 我不会太担心性能,除非它是任务的一部分或者程序需要永远运行。性能的限制因素是创建和销毁 squillions 线程。不管你可以并行化线程做什么,这里的大部分工作都是在你的主线程中完成的。这不是一个非常现实的优化方案,因为在几乎所有瓶颈的情况下,您都会减少线程数并给每个线程更多的工作。登录后,真正的瓶颈可能是终端,其他一切都可以忽略不计。

标签: c macos posix pthreads


【解决方案1】:

检查 pthread_create 的返回值,也许你正在达到资源限制。

 pthread_create() will fail if:

 [EAGAIN]           The system lacked the necessary resources to create
                    another thread, or the system-imposed limit on the
                    total number of threads in a process
                    [PTHREAD_THREADS_MAX] would be exceeded.

 [EINVAL]           The value specified by attr is invalid.

如果您达到资源限制,您可以尝试创建一个线程来连接其他线程,创建一个工作队列并通过队列将工作分配给每个线程,或者如果您控制系统尝试增加它。

【讨论】:

  • 或者对于米老鼠问题的米老鼠修复,稍微展开循环以便创建几个线程,然后加入所有线程,然后再创建几个,依此类推。作业可能会说您必须创建所有这些线程,但它是否说您必须让它们同时运行? ;-)
【解决方案2】:

如果我在 pthread_create 之后立即调用 pthread_join...那么它会阻塞每个线程...实际上一次只会有 2 个线程在运行。

加入线程的另一种方法是将它们创建为分离的。创建并初始化一个 pthread_attr_t, 并将其设置为分离并通过您的 pthread_create 调用传递 attr。

pthread_attr_t  attr;
int             ret;

ret = pthread_attr_init(&attr);
if (ret)
   // error .........

ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

for (....)
{
    //........
    ret = pthread_create(&tArr[tCtr], &attr, compare_thread, (void *)data);
    //.......
}

ret = pthread_attr_destroy(&attr);

也没有要求创建另一个线程的线程必须是加入它的线程。您可以创建一个线程来加入所有其他创建的线程。但这可能超出了这项任务的职责范围。

【讨论】:

    猜你喜欢
    • 2020-03-15
    • 1970-01-01
    • 1970-01-01
    • 2013-02-12
    • 2021-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    相关资源
    最近更新 更多