Давайте посмотрим:
Вы хотите иметь 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
, не все элементы векторов будут обработаны.Однако исправление этих случаев не является ядром этого вопроса ИМХО.
Я избавился от всех видов проверки ошибок, которые вы должны добавить, если этот код станет частью какой-то операционной настройки ...