c - 具有posix线程的数组的内积空间
问题描述
我想从用户读取表 A 和 B 作为输入,并从中创建一个内积空间(a1b1+a2b2+……+anbn)并将其保存在 local_sum 中,然后将其共享给 total_sum 变量。我正在做下面的代码,但是有一个段错误。由于某种原因,表 A 和 B 不能传递给函数 MUL。任何帮助都会很棒,谢谢!
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#define N 2
int p;
int A[N],B[N];
int local_sum;
void *mul(void *arg)
{
int lines, start, end, i, j;
int id = *(int*)arg;
lines = N / p;
start = id * lines;
end = start + lines;
for (i = start; i < end; i++)
local_sum = A[i] * B[i] + local_sum;
return NULL;
}
int main (int argc, char *argv[])
{
int i;
pthread_t *tid;
if (argc != 2)
{
printf("Provide number of threads.\n");
exit(1);
}
p = atoi(argv[1]);
tid = (pthread_t *)malloc(p * sizeof(pthread_t));
if (tid == NULL)
{
printf("Could not allocate memory.\n");
exit(1);
}
printf("Give Table A\n");
for (int i = 0; i < N; i++)
{
scanf("%d", &A[i]);
}
printf("Give Table B\n");
for (int i = 0; i < N; i++)
{
scanf("%d", &B[i]);
}
for (i = 0; i < p; i++)
{
int *a;
a = malloc(sizeof(int));
*a = 0;
pthread_create(&tid[i], NULL, mul, a);
}
for (i = 0; i < p; i++)
pthread_join(tid[i], NULL);
printf("%d", local_sum);
return 0;
}
解决方案
让我们来看看:
你想要有p
线程,处理向量A
和B
.
您必须意识到线程共享相同的内存,并且可能随时被中断。
你有p
线程,都试图写入一个共享变量local_sum
。这会导致不可预知的结果,因为一个线程会覆盖另一个线程之前写入的值。
您可以通过使用互斥锁等确保一个线程对该变量的独占访问来绕过此问题,或者您可以每个线程有一个变量,让每个线程产生一个中间结果,并在加入所有线程后,折叠所有中间结果进入最后一个。
为此,您的 main 应该类似于(假设您的编译器支持最新的 C 标准):
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#define N 2
/* these are variables shared amongst all threads */
int p;
int A[N], B[N];
/* array with one slot per thread to receive the partial result of each thread */
int* partial_sum;
/* prototype of thread function, just to be independent of the place mul will be placed in the source file... */
void *mul(void *arg);
int main (int argc, char** argv)
{
pthread_t* tid;
p = atoi(argv[1]);
const size_t n_by_p = N/p;
if(n_by_p * p != N)
{
fprintf(stderr, "Number of threads must be an integral factor of N\n");
exit(EXIT_FAILURE) ;
}
tid = calloc(p, sizeof(pthread_t));
partial_sum = calloc(p, sizeof(int)) ;
printf("Give Table A\n");
for(size_t i = 0; i < N; ++i)
{
scanf("%d",&A[i]);
}
printf("Give Table B\n");
for(size_t i = 0; i < N; ++i)
{
scanf("%d",&B[i]);
}
for (size_t i =0; i < p; ++i)
{
/* clumsy way to pass a thread it's slot number, but works as a starter... */
int *a;
a = malloc(sizeof(int));
*a = i;
pthread_create(&tid[i], 0, mul, a);
}
for (size_t i = 0; i < p; ++i)
{
pthread_join(tid[i], 0);
}
free(tid);
tid = 0;
int total_sum = 0;
for (size_t i = 0; i < p; ++i)
{
total_sum += partial_sum[i] ;
}
free(partial_sum);
partial_sum = 0;
printf("%d",total_sum);
return EXIT_SUCCESS;
}
您的线程方法mul
现在应该只写入其特定的partial_sum
插槽:
void *mul(void *arg)
{
int slot_num = *(int*)arg;
free(arg);
arg = 0;
const size_t lines = N/p;
const size_t start = slot_num * lines;
const size_t end = start + lines;
partial_sum[slot_num] = 0;
for(size_t i = start; i < end; ++i)
{
partial_sum[slot_num] += A[i]*B[i];
}
return 0;
}
N
注意:此代码运行顺利,只有p
. 如果不满足此条件,由于 中的截断N/p
,不会处理向量的所有元素。但是,解决这些情况并不是这个问题恕我直言的核心。
如果此代码成为某些操作设置的一部分,我没有进行各种错误检查,您应该添加这些检查...
推荐阅读
- xml - 如何在 Schematron 中结合命名空间和元素路径?
- javascript - 如何将重点放在渲染循环中动态创建的 redux 表单上
- java - 对上的 PriorityQueue 比较器不起作用?
- python - 将 dict 中的所有值转换为它们的实际类型
- flutter - 如何在 Flutter 中为 Wrap 渲染特定数量的行?
- python - python列表上的NP.FFT
- c++ - 在 Boost 序列化中展平嵌套命名值对
- javascript - 如何在找到一组 id 的 api 中等待循环完成?SailsJs
- vue.js - 计算函数运行而不调用它
- android - 在 Manifest [Android] 中找不到权限