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

I'll give you a hint:

If you call a function twice manually, you can put its results into two separate variables:

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

You as well can put them into one array:

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

Or into a memory area on heap (obtained via malloc()):

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

In the latter two cases, you can replace the two function calls with

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

Another hint:

For a changed number of threads, you will as well have to change your parameter set.

And another hint:

Thread creation, in your case, can be put into a function:

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);
}

But - there is a caveat: we have a race condition here. As soon as the thread starts, we can return and the stack space occupied by arguments is freed. So we use an improved version here which is useful for cooperation:

  1. We add a field to arguments_t:

    typedef struct arguments {
      char used;
      int start;
      int n;
    } arguments_t;
    
  2. We set used to 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. Set used to 1 once the data has safely copied:

    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 に答える