简体   繁体   English

Pthread计算连续数字的平均值

[英]Pthread to compute average of consecutive numbers

So I am supposed to create a program which computes the average of n consecutive numbers 1...n and compute it in parallel mode using t threads.所以我应该创建一个程序来计算 n 个连续数字 1...n 的平均值,并使用 t 个线程以并行模式计算它。 I decide to use pthread.h, and so far, everything is working fine, the program compiles fine, but it is producing random results:我决定使用 pthread.h,到目前为止,一切正常,程序编译正常,但它产生了随机结果:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>

#define INPUT_SIZE 1000
#define NUM_THREADS 5
#define ARR_SIZE  INPUT_SIZE / NUM_THREADS

struct sum_params {
    int size;
    int* data;
};

int sum_array(struct sum_params* pt) {
  int size = pt->size;
  int* nums = pt->data;

  int sum = 0;
 
  for (int i = 0; i < size; i++) {
     sum += nums[i];
  }

  return sum;  
}

int main(int argc, char ** argv) {
  int arr_size = ARR_SIZE;
  if (INPUT_SIZE % NUM_THREADS != 0) {
    arr_size++;
  }
  int arr[NUM_THREADS][arr_size];
  int n = 1;

  for (int i = 0; i < NUM_THREADS - 1; i++) {
    for (int j = 0; j < arr_size; j++) {
         arr[i][j] = n;
         n++;
      }
  }

  int rem = INPUT_SIZE - arr_size*(NUM_THREADS-1);
  
  for (int j = 0; j < rem; j++) {
    arr[NUM_THREADS-1][j] = n;
    n++;
  }

  for (int j = 0; j < (arr_size-rem); j++) {
    arr[NUM_THREADS-1][rem+j] = 0;
  }

  
  pthread_t threads[NUM_THREADS];
  
  for (int i = 0; i < NUM_THREADS; i++) {
       struct sum_params params;
       params.size = arr_size;

       for (int j = 0; j < arr_size; j++) {
           params.data[j] = arr[i][j];
       }
       

       pthread_create(&threads[i], NULL, (void* (*)(void*))(void*) sum_array, (void*) &params);
  }
  
  int total = 0;
  
  for (int i = 0; i < NUM_THREADS; i++) {
     int thread_sum;
     pthread_join(threads[i], (void*) &thread_sum);
     
     printf("Thread Sum %d: %d\n", i, thread_sum);
     
     total += thread_sum;
  }
  
  double average = ((double) total) / INPUT_SIZE;
  
  printf("%f\n", average);
  pthread_exit(NULL);
  
    return 0;
}

My output:我的 output:

Output 1:
Thread Sum 0: 60100
Thread Sum 1: 140100
Thread Sum 2: 140100
Thread Sum 3: 180100
Thread Sum 4: 180100
700.500000

Output 2:
Thread Sum 0: 100100
Thread Sum 1: 140100
Thread Sum 2: 140100
Thread Sum 3: 180100
Thread Sum 4: 180100
740.500000

Output 3:
Thread Sum 0: 20100
Thread Sum 1: 140100
Thread Sum 2: 140100
Thread Sum 3: 180100
Thread Sum 4: 180100
660.500000

It seems like what is happening is two threads are processing the same sub-array, ie on my last sample output, Threads #2 and #3 processed the sub-array [601,602,...800] when only the 3rd thread should've processed this subarray.似乎正在发生的事情是两个线程正在处理同一个子数组,即在我的上一个示例 output 中,线程 #2 和 #3 处理了子数组 [601,602,...800],而只有第三个线程应该'已经处理了这个子数组。 I'm really confused why my threads are behaving oddly?我真的很困惑为什么我的线程表现得很奇怪? Any ideas on how to fix this?有想法该怎么解决这个吗? Thanks for help!感谢帮助!

Your thread arguments are not correct, and their lifetime are not preserved for the thread to consume.您的线程 arguments 不正确,并且不会保留它们的生命周期以供线程使用。 You have a significant race condition as a result.结果,您有一个重要的竞争条件。 Alternatives:备择方案:

  • You can dynamically allocate each thread structure, send it to the thread, then let the thread consume and destroy it.您可以动态分配每个线程结构,将其发送给线程,然后让线程消耗并销毁它。 Conveying the data back to the caller becomes interesting, and formidable.将数据传回给调用者变得有趣且令人生畏。
  • You can set aside NUM_THREADS structures, basically one for each thread, and send each thread its own, which you then enumerate.您可以留出 NUM_THREADS 个结构,基本上每个线程一个,然后为每个线程发送它自己的,然后枚举。

The latter of these is easy, and shown below.后者很容易,如下所示。 This code runs the same summation for an ascending number of threads, starting with two and finishing with eight.此代码对递增的线程数运行相同的求和,从 2 开始,以 8 结束。 In each case the reported thread accumulations will differ, but the resulting average should always be the same (and it is):在每种情况下,报告的线程累积会有所不同,但生成的平均值应该始终相同(并且确实如此):

#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <pthread.h>

#define INPUT_SIZE 1000
#define MIN_THREADS 2
#define MAX_THREADS 8

struct sum_params
{
    int size;  // [in] size of the partition
    int *data; // [in] base address of partition data
    int sum;   // [out] sum of partition values
};

// thread function
void *sum_array(void *pv)
{
    struct sum_params *pt = pv;
    pt->sum = 0;
    for (int i = 0; i < pt->size; ++i)
        pt->sum += pt->data[i];

    pthread_exit(pv);
}

int main()
{
    // load the array with sequence 1..INPUT_SIZE
    int arr[INPUT_SIZE];
    for (int i = 0; i < INPUT_SIZE; ++i)
        arr[i] = i + 1;

    for (int NUM_THREADS = MIN_THREADS; NUM_THREADS < MAX_THREADS; ++NUM_THREADS)
    {
        // determine partition size
        int part_size = INPUT_SIZE / NUM_THREADS;
        int part_rem = INPUT_SIZE % NUM_THREADS;

        // each thread will get their own structure
        struct sum_params sp[NUM_THREADS];
        int *data = arr;
        for (int i = 0; i < NUM_THREADS; ++i)
        {
            // if there is a remainder of < NUM_THREADS
            //  add one more item to each thread to soak
            //  up that remainder
            sp[i].size = part_size;
            if (part_rem)
            {
                ++sp[i].size;
                --part_rem;
            }

            sp[i].data = data;
            data += sp[i].size;
        }

        // start the threads.
        pthread_t thrds[NUM_THREADS];
        for (int i = 0; i < NUM_THREADS; ++i)
        {
            pthread_create(thrds + i, NULL, sum_array, sp + i);
        }

        // join the threads and accumulate total
        int total = 0;
        for (int i = 0; i < NUM_THREADS; ++i)
        {
            pthread_join(thrds[i], NULL);
            printf("Thread %d total: %d\n", i, sp[i].sum);
            total += sp[i].sum;
        }

        printf("Average: %f\n\n", (double)total / INPUT_SIZE);
    }

    return 0;
}

Output Output

Thread 0 total: 125250
Thread 1 total: 375250
Average: 500.500000

Thread 0 total: 55945
Thread 1 total: 166833
Thread 2 total: 277722
Average: 500.500000

Thread 0 total: 31375
Thread 1 total: 93875
Thread 2 total: 156375
Thread 3 total: 218875
Average: 500.500000

Thread 0 total: 20100
Thread 1 total: 60100
Thread 2 total: 100100
Thread 3 total: 140100
Thread 4 total: 180100
Average: 500.500000

Thread 0 total: 14028
Thread 1 total: 41917
Thread 2 total: 69806
Thread 3 total: 97695
Thread 4 total: 124749
Thread 5 total: 152305
Average: 500.500000

Thread 0 total: 10296
Thread 1 total: 30745
Thread 2 total: 51194
Thread 3 total: 71643
Thread 4 total: 92092
Thread 5 total: 112541
Thread 6 total: 131989
Average: 500.500000

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM