我正在编写一个用于赋值的程序,该程序使用线程在两个给定数组之间实现矩阵乘法。

我必须给出要用作命令行参数的线程数,如果它们的数量小于第一个数组的行数,请重用一些相同的线程,直到完成整个作业。

我设法使其工作,但仅对数组的每一行使用一个线程。
例如,如果a具有5x5乘法并且使用少于5个线程,则我会遇到段错误,这是有道理的。

我的问题是:在该线程完成其工作后,如何重用该线程?
在前面的示例中,我的意思是,如果我想为5x5使用2个线程,则我的程序应该像这样工作:

线程1->第1行

线程2->行2

线程2->行3

线程1->第4行

等等。

最佳答案

您有几种可能,但是主要思想是必须监视线程以检测它们何时完成工作,并有办法知道是否还有要做的事情。

首先想到的是拥有一个专用线程来跟踪所有正在运行的线程,并在完成后将其回收。但是为了做到这一点,您需要一种使线程同步的机制,可以使用信号量或互斥量或消息来实现,但是如果您尚未为此目的而编写代码,则可能会很麻烦。 。

第二种方法是简单地要求他们进行回收,因为他们知道完成的时间。在许多其他语言中,有一种称为延续的机制,可以让您确切地知道这一点,但是由于我们正在处理C,因此需要手动完成。幸运的是,这里的延续实际上只是一项任务。

因此,调用延续的机制实际上只是一个函数,它将首先运行要由线程执行的任务,然后执行以下任一操作:

  • 检查任务列表。该任务列表必须在设置时填写任务
  • 需要完成的所有工作
  • 将线程添加到可用线程队列中,其他线程必须再次检查该线程,然后重新分配一个新任务

  • 显然,第一种选择会更容易,并且在您的情况下,您已经在设置时知道了必须执行的操作,因此您的设置功能可以填充任务列表,然后根据需要启动尽可能多的线程,并让它们运行自己做回收。

    这是一个简单的框架,您可以从以下开始:
     typedef struct {
        /* task related data */
     } task_t;
    
     // basic list structure
     typedef struct {
       list_t *next;
       void *data; // here app specific data
     } list_t;
    
     list_t task_list; // your task list
    
     // a few operators to manipulate a list
     // implementation must use a mutex to avoid race conditions
     void list_push(list *l, void *data);
     void *list_pop(list *l);
    
    
     // thread function
    
     void do_task(task_t *task){
         while (task) {
           run_task(task); // that would be the matrix related function
           task = list_pop(&task_list);
     }
    
     // here a simple define for the number of threads
     // you might want to check the number of available cores instead
    
     #define MAX_THREAD_COUNT 4
    
     int main() {
    
       pthread_t threads[MAX_THREAD_COUNT];
    
       setup_task_list();  // push all the work that must be done in the list
       int i;
       for (i = 0; i < MAX_THREAD_COUNT; i++) {
          pthread_create(threads + i, NULL, do_task, list_pop(&task_list));
       }
    
       // here wait for all the threads, or detach them
    
     }
    

    这是您可以做什么的基本概述,应该可以帮助您入门。
    关于SO处理C链表,有几个问题。这里的一个必须同步,不应阻塞,并且为空时返回NULL

    09-26 01:04
    查看更多