0

我已经开始在 Uni 中学习 C,现在我被困在 posix 线程上。我有一个程序,它有一个单线程、2 个线程和 4 个线程作为讲座的例子。我需要你的帮助来将这个程序从 4 扩展到 8/16/32,它会如何执行不同的操作?

先感谢您。

这是4线程程序的代码:

/****************************************************************************
  This program finds groups of three numbers that when multiplied together
  equal 98931313. Compile with:

    cc -o factorise4 factorise4.c -lrt -pthread

  Kevan Buckley, University of Wolverhampton, October 2012
*****************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <sys/stat.h>
#include <string.h>
#include <time.h>
#include <pthread.h>
#include <math.h>

#define goal 98931313

typedef struct arguments {
  int start;
  int n;
} arguments_t;

void factorise(int n) {
  pthread_t t1, t2, t3, t4;
//1st pthread
  arguments_t t1_arguments;
  t1_arguments.start = 0;
  t1_arguments.n = n;
//2nd pthread
  arguments_t t2_arguments;
  t2_arguments.start = 250;
  t2_arguments.n = n;
//3rd pthread
  arguments_t t3_arguments;
  t3_arguments.start = 500;
  t3_arguments.n = n;
//4th pthread
  arguments_t t4_arguments;
  t4_arguments.start = 750;
  t4_arguments.n = n;

  void *find_factors();
  //creating threads
  pthread_create(&t1, NULL, find_factors, &t1_arguments);
  pthread_create(&t2, NULL, find_factors, &t2_arguments);
  pthread_create(&t3, NULL, find_factors, &t3_arguments);
  pthread_create(&t4, NULL, find_factors, &t4_arguments);

  pthread_join(t1, NULL);
  pthread_join(t2, NULL);
  pthread_join(t3, NULL);
  pthread_join(t4, NULL);
}

//Using 3 loops, 1 loop represents one value that we need to find, and go throught it until 98931313 not will be find.
void *find_factors(arguments_t *args){
  int a, b, c;
  for(a=args->start;a<args->start+250;a++){
    for(b=0;b<1000;b++){
      for(c=0;c<1000;c++){
        if(a*b*c == args->n){
           printf("solution is %d, %d, %d\n", a, b, c);// Printing out the answer
        }
      }
    }
  }
}

// Calculate the difference between two times.
long long int time_difference(struct timespec *start, struct timespec *finish, long long int *difference) {
  long long int ds =  finish->tv_sec - start->tv_sec; 
  long long int dn =  finish->tv_nsec - start->tv_nsec; 

  if(dn < 0 ) {
    ds--;
    dn += 1000000000; 
  } 
  *difference = ds * 1000000000 + dn;
  return !(*difference > 0);
}
//Prints elapsed time
int main() {
  struct timespec start, finish;   
  long long int time_elapsed;

  clock_gettime(CLOCK_MONOTONIC, &start);

  factorise(goal); //This is our goal = 98931313

  clock_gettime(CLOCK_MONOTONIC, &finish);
  time_difference(&start, &finish, &time_elapsed);
  printf("Time elaipsed was %lldns or %0.9lfs\n", time_elapsed, (time_elapsed/1.0e9)); 

  return 0;
}
4

2 回答 2

1

我给你一个提示:

如果您手动调用一个函数两次,您可以将其结果放入两个单独的变量中:

int y0 = f(0);
int y1 = f(1);

您也可以将它们放入一个数组中:

int y[2];
y[0] = f(0);
y[1] = f(1);

或进入堆上的内存区域(通过 获得malloc()):

int * y = malloc(2 * sizeof(*y));
y[0] = f(0);
y[1] = f(1);

在后两种情况下,您可以将两个函数调用替换为

for (i = 0; i < 2; i++) {
    y[i] = f(i);
}

另一个提示:

对于更改的线程数,您还必须更改参数集。

还有一个提示:

在您的情况下,线程创建可以放入一个函数中:

void facthread_create(pthread_t * thread, int start, int n)
{
    arguments_t arguments;
    arguments.start = start;
    arguments.n = n;

    void *find_factors();
    //creating thread
    pthread_create(thread, NULL, find_factors, &arguments);
}

但是 - 有一个警告:我们这里有一个竞争条件。线程一启动,我们就可以返回并arguments释放所占用的堆栈空间。所以我们在这里使用了一个改进的版本,它对合作很有用:

  1. 我们添加一个字段arguments_t

    typedef struct arguments {
      char used;
      int start;
      int n;
    } arguments_t;
    
  2. 我们将 used 设置为 0:

    void facthread_create(pthread_t * thread, int start, int n)
    {
        arguments_t arguments;
        arguments.start = start;
        arguments.n = n;
        arguments.used = 0;
    
        void *find_factors();
        //creating thread
        pthread_create(thread, NULL, find_factors, &arguments);
        while (!arguments.used); // wait until thread has "really" started
    }
    
  3. 数据安全复制后,将 used 设置为 1:

    void *find_factors(arguments_t *args){
        arguments_t my_args = *args; // is this valid? Don't remember... If not, do it element-wise...
        *args.used = 1; // Inform the caller that it is safe to continue
        int a, b, c;
        for(a=my_args.start;a<my_args.start+250;a++){
            ...
    
于 2013-10-28T17:52:59.807 回答
0

你应该得到一个命令行参数(也许 -t 用于线程)。然后,不要从 main 调用 factorise,而是有一个 for 循环,该循环使用从循环号计算的参数创建线程。就像是:

for (int i = 0; i < threads; i++) {  
    arguments.start = 250 * i;
    arguments.n = n;  
    pthread_start(...)
} 

请注意,为清楚起见,您应该在 for 循环之前分配参数结构。

如果您需要更多帮助,请告诉我。

这里有更多帮助:
0)从命令行获取线程数和跳过(在你的情况下为 250)。
1)创建一个控制结构,其中包含线程的参数,线程ID等
。2)使用参数,分配控制结构并填充它
。3)做一个for循环来产生胎面。
4)做另一个for循环以等待线程完成。

对于一些额外的复杂性,您可以引入一个全局变量,任何线程都可以设置该变量以向其他线程发出工作已完成并且它们应该退出的信号。但是在你得到正确的简单案例之前不要这样做。

如果您发布一些更新的代码,我会为您提供更多帮助。

于 2013-10-28T17:08:52.553 回答