• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

Psicopunk

Threads em C

30 mensagens neste tópico

Ei pessoal...

Estou a aprender sozinho um pouco de pthreads. No entanto, como estou a aprender sozinho vou tendo alguns problemas. Fiz um código em que crio 2 Threads para tratar duas partes diferentes dum vector. Isto nao tem interesse practico nenhum, apenas serve pra mecanizar e aprender.

No entanto quando compilo tem um comportamente em que fica num ciclo infinito em que nao faz trabalho util.

Aqui está o código...

#include<pthread.h>
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

#define NUM_THREADS	2
#define TAM_VEC		10



int vector[TAM_VEC]={1,2,3,4,5,6,7,8,9,10};

void *Func_Thread(void *threadid)
{
int i, tid;
tid = (int)threadid;

if(tid==0)
{
	for(i=0;i<TAM_VEC;i+2)
	{
	vector[i]=vector[i]*2;
	printf("A thread nº %d operou sobre o vector[%d] e colocou la %d\n", tid,i,vector[i]);
	}
}
else
{
	for(i=1;i<TAM_VEC;i+2)
	{
	vector[i]=vector[i]*2;
	printf("A thread nº %d operou sobre o vector[%d] e colocou la %d\n", tid,i,vector[i]);
	}
}
pthread_exit(NULL);
}

int main()
{
pthread_t threads[NUM_THREADS];
int rc,t;

for(t=0;t<NUM_THREADS;t++)
{
printf("A criar a Thread nº %d\n",t);
rc=pthread_create(&threads[t],NULL,Func_Thread,(void *)t);
if(rc){
          printf("ERROR;return code form pthread_create() is %d \n",rc);
      }
}
pthread_exit(NULL);

}

Isto foi compilado com:

gcc Thread_exercicio2.c -pthread -o Thread_exercicio2 

Se alguém compreender o erro, agradeço...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Aparentemente tens um erro nos fors (devia ser i+=2 e não i+2).

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

->  alteram o i

i++          igual      i = i + 1

i += 2      igual      i = i + 2

->  n alteram o i

i+2       

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

É verdade... têm razão.

Não tinha reparado! :-[

Obrigado

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Aproveito este tópico para colocar a minha dúvida.  :hmm:

Estou a fazer um programa em C e em linux (para um trabalho da escola), que consiste sobretudo na multiplicação de matrizes. Mas tenho de utilizar threads.  :mad:

Um processo é um programa que por sua vez se divide em threads. Deram-me uma dica mas não sei como posso pô-la em prática e se me ajudassem agradecia (não pretendo k façam o meu trabalho mas apenas k me expliquem como posso/devo fazer). Por exemplo, imaginem a multiplicação de 2 matrizes em que a matriz resultante dessa multiplicação é uma matriz 4x4. A dica que me deram para este caso, uma vez que a matriz tem dimensões pequenas, foi criar 4 threads para executar cada um dos cálculos. A minha dúvida é:

1º O programa irá criar uma thread para os cálculos todos, certo?

2º Usando a dica que me deram, como posso aplicar 4 threads criadas à parte, com a função pthread_create(), nessa matriz?

Ja pesquisei na net e não encontrei nada. Se me puderem explicar agradecia.  :P

Abçs

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Não percebi muito bem a tua solução, mas a sugestão que te dou, é criares uma thread para calcular o valor de cada posição da matriz resultante. Dependendo das dimensões da matriz (e da máquina em que correres o programa), poderá ser ou não uma boa solução.

Se quiseres uma solução que se adapte às matrizes, podes ter em conta a dimensões das mesma. Supondo que têm dimensão l*n e n*c, quando o valor de n for baixo não deves usar a solução que sugeri, pois terá poucos cálculo por thread. Aí, se o valor de c não for também baixo, podes criar uma thread para calcular cada linha da matriz resultante, ou se este for baixo e o valor de l não for, o melhor será ter uma thread para cada coluna.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Deste a resposta que "queria".  :P Só que o meu problema é como é que aplico isso. Eu tenho uma função que vai fazer a multiplicação das matrizes. A minha duvida é, como é que, numa matriz de 10x10, crio 10 threads (uma para cada multiplicação - tipo, linha 1 coluna 1 por ex. 2x5, linha 1 coluna 2 10x2, etc.) Mesmo que aplique uma thread por linha, por exemplo, como é que o faço. A minha duvida é esta. É que o pthread_create() apenas me irá criar uma thread que vai ser aplicada em k parte da matriz?  :hmm:

Faço-me entender?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Quanto à concretização disso é algo em que não te posso ajudar. Trabalho bastante com threads, mas é em Java. Noutras linguagens nunca o fiz.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Tens que passar por parâmetros à função que executas para cada thread qual a linha e coluna que vão ser calculadas pela thread. Em Linux não sei como isso se processa.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Deste a resposta que "queria".  :P Só que o meu problema é como é que aplico isso. Eu tenho uma função que vai fazer a multiplicação das matrizes. A minha duvida é, como é que, numa matriz de 10x10, crio 10 threads (uma para cada multiplicação - tipo, linha 1 coluna 1 por ex. 2x5, linha 1 coluna 2 10x2, etc.) Mesmo que aplique uma thread por linha, por exemplo, como é que o faço. A minha duvida é esta. É que o pthread_create() apenas me irá criar uma thread que vai ser aplicada em k parte da matriz?  :hmm:

Faço-me entender?

Tens a certeza que queres criar uma thread para cada multiplicação? Eu acho que fazia mais sentido que tivesse uma thread que multiplicasse 2 matrizes e devolvesse o resultado...

De qualquer das formas, tu passas um apontador void para a thread, isto é, ela recebe qualquer coisa.

A minha sugestão é que cries uma estrutura com as matrizes e variaveis com os tamanhos delas e passes à(s) thread(s):

typedef struct
{
int matriz1[22][22] , matriz2[22][22] , matrizResultado[22][22];
int lin1 , col1 , lin2 , col2 , linR , colR;
} coiso;

void * thread_func( void * arg )
{
coiso * pointer = (coiso *) arg;
// multiplica pointer->matriz1 por pointer->matriz2
// e coloca resultado em pointer->matrizResultado
return NULL;
}

// codigo ...

coiso r;
// ler matrizes para a estrutura na variavel r

pthread_create( & tid , NULL , thread_func , (void *) & r );

// resultado em r.matrizResultado

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Isso não faz muito sentido pois teria que existir uma cópia das matrizes originais para cada thread, o que dá origem a um desperdício imenso de espaço. Além disso, como é que cada thread ia saber qual era a linha e coluna que devia multiplicar?

Se na struct criada tiveres apontadores para as duas matrizes, os seus tamanhos, um inteiro para o resultado (dado que a multiplicação de uma linha por uma coluna dá um único número), e dois inteiros para os índices da linha e coluna que uma thread vai multiplicar, acho que deves chegar lá.

Depois é criares um array dessas structs, com as dimensões da matriz resultado, inicializá-las para apontarem para as matrizes a multiplicar e respectivos tamanhos, colocar nos índices a própria posição de cada struct, e criar threads ordenadamente.

Claro que se no programa todo apenas vais multiplicar duas matrizes de cada vez, podes simplificar a struct removendo os apontadores para as matrizes e os seus tamanhos, passando-os para variáveis globais e mantendo na struct apenas um campo para o resultado e 2 para os índices.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Tens a certeza que queres criar uma thread para cada multiplicação? Eu acho que fazia mais sentido que tivesse uma thread que multiplicasse 2 matrizes e devolvesse o resultado...

Vou fazer a multiplicação de duas ou várias matrizes e deram-me uma sugestão em como poderia fazer a multiplicação e o k eu disse anteriormente era uma maneira. porque imagina k tens uma matriz de 3000x3000. Não vais criar 3000 threads mas tb não vais criar só uma percebes? Ou fica lento a processar a informação ou ocupas muito espaço com as threads. Tenho para isso de arranjar maneira de optimizar a multiplicação.  ;)

Mas penso k o TheDark já me deu umas luzes em como posso fazer a multiplicação. Penso tb, k não será necessário utilizar estruturas.

Obg a todos  :P

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

TheDark,

Penso que fui explicito (até nos comentários do código) : a minha sugestão era que a thread fizesse a multiplicação toda das matrizes e não apenas uma linha por uma coluna.

Eu não sei se o propósito das threads está definido... daí esta sugestão. Pelo que entendi no post da dúvida, isso de ter uma thread a calcular uma linha por coluna tinha sido uma sugestão dum colega...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Pelo que entendi no post da dúvida, isso de ter uma thread a calcular uma linha por coluna tinha sido uma sugestão dum colega...

Olha que boa ideia... está ai uma boa ideia para acelerar o calculo de matrizes em ambientes com varios processadores.

Juntar um OpenMP e está uma bela ideia.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
Penso tb, k não será necessário utilizar estruturas.

Se quiseres passar vários valores à função da thread, passar um apontador para uma estrutura é a maneira mais elegante :D

TheDark,

Penso que fui explicito (até nos comentários do código) : a minha sugestão era que a thread fizesse a multiplicação toda das matrizes e não apenas uma linha por uma coluna.

Eu não sei se o propósito das threads está definido... daí esta sugestão. Pelo que entendi no post da dúvida, isso de ter uma thread a calcular uma linha por coluna tinha sido uma sugestão dum colega...

Certo. Mas tem mais lógica várias threads para uma multiplicação (multiplicar várias linhas por colunas em simultâneo), do que uma thread para uma multiplicação. Pelo menos do meu ponto de vista...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Sim mas caso fosse para uma matriz muito simples como o exemplo k dei (4x4). Agr se for uma matriz de por exemplo 3000x3000 nao compensa ter 3000 threads. Para isso,  temos de arranjar maneira de simplificar os calculos

Abç

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Eu não disse para teres 3000 threads. Podes muito bem limitar o número de threads activas em cada momento.

Se conseguires simplificar os cálculos, o pessoal que ainda não fez Álgebra Linear vai agradecer-te :D

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

LOL... ja fiz Algebra e continuo a complicar os calculos  :biggrin:

O k eu kis dizer foi, se tivermos uma matriz de 3000x3000 CLARO k não vamos fazer 3000 threads. Tem de haver forma de simplificar isso. Alguém me ajuda a fazer uma matriz na estrutura.

Tipo, posso ter isto?

struct threads

{

  int dimensao, pos, nthreads, *matriz1, *matriz2, *matriz_resultante (com 1 ou com 2 *?) //matriz_resultante da multiplicação das matrizes 1 e 2.

};

...

void qq coisa (int threads, ...)

{

      ...

      if (pthread_createpthread_create(&tmult, NULL, multiplicacao_threads, &data[t]) != 0)

ERROR(-1, "pthread_create() failed!\n");

    ....

}

void multiplicacao_threads (...) //Nesta função tenho duvidas na reserva de memoria caso a matriz esteja na estrutura. Por outras palavras, não sei como se faz. Se me pudessem ajudar agradecia.

Abçs

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

E ja agr, uma vez que estou a tentar perceber como aloco memoria de uma matriz utilizando estruturas, o porque disto me colocar o valor 8802188?

Codigo:

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>

struct threads
{
        int **matriz;
};

void funcao (void);

void main ()
{
        funcao();
}
void funcao(void)
{
        struct threads exp;

        exp.matriz=(int **)malloc (sizeof (int));
        printf ("memoria alocada\n%d", exp.matriz);
        getch();
}

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

E ja agr, uma vez que estou a tentar perceber como aloco memoria de uma matriz utilizando estruturas, o porque disto me colocar o valor 8802188?

O valor que te dá é o valor da posição de memória onde está um apontador que aponta para um inteiro. Atenção que o tipo de retorno da função main deve ser int e não void. E se queres imprimir o valor do exp.matriz (que é um apontador basicamente) deves usar o formato "%p" no printf. Mais um detalhe: a biblioteca conio.h não é ANSI standard, pelo que se queres que o teu programa seja portável (corra em linux por exemplo) deves ter cuidado com as biliotecas que incluis e com as modificações que podem ser precisas fazer a nível de compilação/linkagem do teu programa.

#include <stdio.h>
#include <stdlib.h>

struct threads
{
        int **matriz;
};

void funcao (void);

int main(void)
{
        funcao();
        
        return 0;
}

void funcao(void)
{
        struct threads exp;

        exp.matriz=(int **)malloc (sizeof (int));
        printf("memoria alocada\n%p", exp.matriz);
        getchar();
        free(exp.matriz);
}

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Eu fiz isso no dev apenas para experimentar a parte da alocação de memória usando matrizes que se encontram nas estruturas. Mas de qq das maneiras, como eu tinha feito (à excepção dos erros) estava bem? :D

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Alocaste memória para os apontadores de 1º nível, mas não alocaste para os de 2º nível. Além disso, o programa até funciona, mas foi uma questão de sorte, porque o tamanho do tipo int é igual ao do tipo int**. Se utilizasses por exemplo char **a=(char**)malloc(sizeof(char)); quando executasses o programa e tentasses escrever em a[0][0] possivelmente dar-te-ia um erro, porque o tamanho de char é menor que o de char**. E ainda, estás a alocar memória para apenas 1 elemento.

Para alocares dinamicamente apontadores duplos, tens que fazer algo deste género:

 //Aqui alocamos espaço para 10 apontadores para int. Isto é a 1ª dimensão da matriz
int **a=(int**)malloc(10*sizeof(int*));
int i;
for (i=0; i<10; ++i)
//Aqui alocamos espaço para 50 ints. Isto é a 2ª dimensão da matriz.
a[i]=(int*)malloc(50*sizeof(int));

//e agora temos uma matriz com 10x50
a[5][20] = 100;

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

:( Obg. Fiquei a perceber  :D Sendo assim, a declaração que fiz da matriz na estrutura está correcta?

Mais uma vez obg :biggrin:

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora