[英]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*) ¶ms);
}
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:
备择方案:
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.