Ваша первая проблема с потоками здесь:
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
struct data st;
st.p = 2;
for(int x = 0; x < st.p; x++){
st.linie[x] = A[i][x];
st.coloana[x] = B[x][j];
}
pthread_create(&threads[count], NULL, func, &st);
count++;
}
}
Все потоки получают указатель на одну и ту же переменную &st
, которая выходит из области действия после каждого вызова pthread_create()
.Вы должны убедиться, что каждый поток получает свою собственную переменную, и что эта переменная длится до тех пор, пока поток не выйдет.
Чтобы исправить это, например, вы можете попробовать:
struct data st[n * m];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
st[count].p = 2;
for (int x = 0; x < st[count].p; x++)
{
st[count].linie[x] = A[i][x];
st[count].coloana[x] = B[x][j];
}
int rc = pthread_create(&threads[count], NULL, func, &st[count]);
if (rc != 0)
…report pthread creation error…
count++;
}
}
Это даеткаждый поток имеет свой собственный struct data
для работы, и структура переживает цикл pthread_join()
.
Я не совсем уверен, что это хорошая схема - сделать одну копию соответствующих частей двух массивов.для каждой темы.Это не слишком больно в размере 2x2, но в 20x20, это начинает быть болезненным.Потокам следует указать, какую строку и столбец обрабатывать, а также указать указатели на исходные матрицы и т. Д.Пока никакой поток не изменяет исходные матрицы, проблем с чтением данных не возникает.
Обновленный ответ, который заменяет предыдущий недействительный код, связанный с pthread_join()
(как отмечено oftigus в комментарии ) с этим рабочим кодом.Есть причина, которую я обычно проверяю перед публикацией!
В целом, в цикле pthread_join()
следует избегать приведений типа (void **)
.Один правильный рабочий способ справиться с этим:
for (int i = 0; i < n * m; i++)
{
void *vp;
int rc = pthread_join(threads[i], &vp);
if (rc == 0 && vp != NULL)
{
rez[i] = vp;
printf("(%s) %d ", rez[i], atoi(rez[i]));
free(rez[i]);
}
}
putchar('\n');
Передает указатель на переменную void *
в pthread_join()
.Если он находит информацию для запрошенного потока, то pthread_join()
заставляет эту переменную void *
содержать значение, возвращаемое функцией потока.Затем это можно использовать, как показано - обратите внимание на обработку ошибок (хотя я отмечаю, что пример в спецификации POSIX для pthread_join()
игнорирует возвращаемое значение из pthread_join()
с приведением (void)
к результату).
Я не вижу, где вы используете res
или C
.
Результат, который я получаю:
(21) 21 (13) 13 (63) 63 (37) 37
где значение в скобках является строкой, а значение снаружи преобразуется в atoi()
.Это похоже на правильный ответ для умножения A
на B
(в таком порядке).
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
struct data
{
int p;
int linie[20];
int coloana[20];
};
static void *func(void *args)
{
struct data *st = (struct data *)args;
int c = 0;
for (int k = 0; k < st->p; k++)
{
c += st->linie[k] * st->coloana[k];
}
char *rez = (char *)malloc(5);
sprintf(rez, "%d", c);
return rez;
}
int main(void)
{
int n = 2;
int m = 2;
int A[2][2] = {{1, 2}, {4, 5}};
int B[2][2] = {{7, 3}, {7, 5}};
char *rez[n * m];
pthread_t threads[n * m];
int count = 0;
struct data st[n * m];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
st[count].p = 2;
for (int x = 0; x < st[count].p; x++)
{
st[count].linie[x] = A[i][x];
st[count].coloana[x] = B[x][j];
}
int rc = pthread_create(&threads[count], NULL, func, &st[count]);
if (rc != 0)
{
fprintf(stderr, "Failed to create thread %d for cell C[%d][%d]\n", count, i, j);
exit(1);
}
count++;
}
}
for (int i = 0; i < n * m; i++)
{
void *vp;
int rc = pthread_join(threads[i], &vp);
if (rc == 0 && vp != NULL)
{
rez[i] = vp;
printf("(%s) %d ", rez[i], atoi(rez[i]));
free(rez[i]);
}
}
putchar('\n');
return 0;
}