Внутренний продуктовый массив массивов с посиксами - PullRequest
0 голосов
/ 27 мая 2018

Я хочу прочитать в качестве входных данных таблицы 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;
}

Ответы [ 2 ]

0 голосов
/ 28 мая 2018

Давайте посмотрим:

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

Я избавился от всех видов проверки ошибок, которые вы должны добавить, если этот код станет частью какой-то операционной настройки ...

0 голосов
/ 27 мая 2018
if (tid=NULL)

->

  if (tid==NULL)

и

for (i=start;i<end;i++)

Полагаю, нам нужно

for (i=0;i<end-start;i++)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...