Как получить одно правильное значение из функции, которая распараллелена многопоточностью - PullRequest
0 голосов
/ 19 июня 2019

Для более быстрого расчета, попытайтесь сделать мой метод распараллеленным на 4 потока. Где потоки производят 4 отдельных вычисления, ожидал ли я одновременной операции и по одной переменной.

#include <stdio.h>
#include <unistd.h>
#include <pthread.h>

static int x, j=5;

void *print_count (void *dummy)
{
  for(int i=0;i<1000;i++){
  x+=j;
  }
}

int main ()
{
pthread_t p1, p2, p3, p4;

pthread_create (&p1, NULL, print_count, NULL);
pthread_create (&p2, NULL, print_count, NULL);
pthread_create (&p3, NULL, print_count, NULL);
pthread_create (&p4, NULL, print_count, NULL);

pthread_join (p1, NULL);
pthread_join (p2, NULL);
pthread_join (p3, NULL);
pthread_join (p4, NULL);

printf("Actual output: %d \nExpected output: 5000\n", x);

return 0;

}

Я ожидаю, что выход 5000, как приращение 5 и цикл 1000 раз. Но фактический результат, прежде всего, не статичен, он всегда изменяется и составляет около 4 раз из 5000, потому что потоки вычисляют print_count отдельно.

Спасибо

1 Ответ

0 голосов
/ 19 июня 2019

Если вы находитесь под C11, вы можете использовать _Atomic

Конечно, каждый поток должен работать над диапазоном значений (не с полным набором), передайте struct:

#include <stdio.h>
#include <stdatomic.h>
#include <pthread.h>

_Atomic int x;
static int j = 5;

struct range {
    int from, to;
};

void *print_count(void *data)
{
    struct range *range = data;

    for (int i = range->from; i < range->to; i++) {
        x += j;
    }
    return NULL;
}

int main(void)
{
    pthread_t p1, p2, p3, p4;
    struct range ranges[] = {
        {0, 250},
        {250, 500},
        {500, 750},
        {750, 1000}
    };

    pthread_create(&p1, NULL, print_count, &ranges[0]);
    pthread_create(&p2, NULL, print_count, &ranges[1]);
    pthread_create(&p3, NULL, print_count, &ranges[2]);
    pthread_create(&p4, NULL, print_count, &ranges[3]);

    pthread_join(p1, NULL);
    pthread_join(p2, NULL);
    pthread_join(p3, NULL);
    pthread_join(p4, NULL);

    printf("Actual output: %d \nExpected output: 5000\n", x);
    return 0;
}

Или составной литерал:

pthread_create(&p1, NULL, print_count, (int []){  0,  250});
pthread_create(&p2, NULL, print_count, (int []){250,  500});
pthread_create(&p3, NULL, print_count, (int []){500,  750});
pthread_create(&p4, NULL, print_count, (int []){750, 1000});

...

void *print_count(void *data)
{
    int *range = data;

    for (int i = range[0]; i < range[1]; i++) {
        x += j;
    }
    return NULL;
}

для разделения задачи.

Выход:

Actual output: 5000 
Expected output: 5000
...