Partage
  • Partager sur Facebook
  • Partager sur Twitter

Les threads et un processeur multicoeur

Sujet résolu
21 novembre 2017 à 17:19:03

Bonjour a tous, je me familiarise avec les threads et j' ai une question :)

Voici mon code de test :

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

# define MAX_VAL 20u

typedef struct				s_data
{
	unsigned int			val;
	pthread_cond_t			cond;
	pthread_mutex_t			mutex;
}							t_data;

int							init_struct_data(t_data *data)
{
	if (data == NULL)
		return (-1);
	data->val = 0u;
	if (pthread_cond_init(&data->cond, NULL) != 0)
		return(-1);
	return (pthread_mutex_init(&data->mutex, NULL));
}

void						*func_check(void *data_tmp)
{
	t_data					*data;

	if (data_tmp == NULL)
		pthread_exit(NULL);
	data = (t_data *)data_tmp;
	while (1)
	{
		if (pthread_mutex_lock(&data->mutex) != 0 || 
				pthread_cond_wait(&data->cond, &data->mutex) != 0)
			pthread_exit(NULL);
		data->val = 0;
		printf("\tval = %u\n", data->val);
		if (pthread_mutex_unlock(&data->mutex) != 0)
			pthread_exit(NULL);
	}
	pthread_exit(data);
}

int							main(void)
{
	unsigned int			i;
	t_data					data;
	pthread_t				thread_check;

	if (init_struct_data(&data) != 0)
		return (EXIT_FAILURE);
	if (pthread_create(&thread_check, NULL, func_check, &data) == -1)
		return (EXIT_FAILURE);
	for (i = 0; i < 1000; i++)
	{
		printf("val = %u\n", data.val);
		if (data.val++ > MAX_VAL)
			if (pthread_mutex_lock(&data.mutex) != 0 ||
					pthread_cond_signal(&data.cond) != 0 ||
					pthread_mutex_unlock(&data.mutex) != 0)
				return (EXIT_FAILURE);
	}
	pthread_cancel(thread_check);
	return (EXIT_SUCCESS);
}

C' est un code simple qui incrémente une variable 1000 fois pendant un thread la reset a 0 s'il cette variable dépasse 20.

Je precise que mon processeur est un quadricoeurs donc si j' ai bien compris je gere vraiment 4 threads en paralele (c'est bien ca ?)

Voici mon resultat : 

val = 0
...
val = 27
val = 1
        val = 0
val = 2
...
val = 48
val = 1
        val = 0
val = 2
...
val = 48
        val = 0
val = 1
...
val = 32
        val = 0
val = 1
...
val = 38
        val = 0
val = 1
...
val = 23
        val = 0
val = 1
...
val = 28
        val = 0
val = 1
...
val = 30
        val = 0
val = 1
...
val = 47
        val = 0
val = 1
...
val = 28
        val = 0
val = 1
...
val = 26
val = 1
        val = 0
val = 2
...
val = 30
        val = 0
val = 1
...

Je peux comprend pour pour le premier je monte a 27 le temps que le thread soit cree et operationnel. Mais pourquoi apres val n' est pas set a 0 des quelle depasse 20 ?

Merci :)

-
Edité par Azuraul 21 novembre 2017 à 17:20:46

  • Partager sur Facebook
  • Partager sur Twitter
21 novembre 2017 à 17:43:16

Si je m'endors (dans les nuages ;) ) lorsque je me verse un verre d'eau, ça arrive que ça déborde.

Regarde la partie VI-B de ce tutoriel cela t'expliquera le soucis et comment le résoudre !
  • Partager sur Facebook
  • Partager sur Twitter
21 novembre 2017 à 21:34:40

Azuraul a écrit:

Je precise que mon processeur est un quadricoeurs donc si j' ai bien compris je gere vraiment 4 threads en paralele (c'est bien ca ?)

À peu près, sauf que dans ton cas tu as plein de synchronisations donc ton programme va juste être infiniment plus lent et n'exploitera pas plus d'un cœur à la fois.
  • Partager sur Facebook
  • Partager sur Twitter
Un vrai cours de: (C | C++ | Haskell débutant | Haskell intermédiaire | Rust).
22 novembre 2017 à 8:07:59

Merci neuneutrinos pour le lien :D 

Ce code fonctionne :

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

# define MAX_VAL 20u

typedef struct				s_data
{
	unsigned int			val;
	pthread_cond_t			cond_check;
	pthread_cond_t			cond_inc;
	pthread_mutex_t			mutex;
}							t_data;

int							init_struct_data(t_data *data)
{
	if (data == NULL)
		return (-1);
	data->val = 0u;
	if (pthread_cond_init(&data->cond_check, NULL) != 0 || 
			pthread_cond_init(&data->cond_inc, NULL) != 0)
		return(-1);
	return (pthread_mutex_init(&data->mutex, NULL));
}

void						*func_check(void *data_tmp)
{
	t_data					*data;

	if (data_tmp == NULL)
		pthread_exit(NULL);
	data = (t_data *)data_tmp;
	while (1)
	{
		if (pthread_mutex_lock(&data->mutex) != 0 ||
				pthread_cond_wait(&data->cond_check, &data->mutex) != 0)
			pthread_exit(NULL);
		data->val = 0;
		printf("\tval = %u\n", data->val);
		if (pthread_cond_signal(&data->cond_inc) != 0 ||
				pthread_mutex_unlock(&data->mutex) != 0)
			pthread_exit(NULL);
	}
	pthread_exit(data);
}

int							main(void)
{
	unsigned int			i;
	t_data					data;
	pthread_t				thread_check;

	if (init_struct_data(&data) != 0)
		return (EXIT_FAILURE);
	if (pthread_create(&thread_check, NULL, func_check, &data) == -1)
		return (EXIT_FAILURE);
	for (i = 0; i < 1000; i++)
	{
		printf("val = %u\n", data.val);
		if (data.val++ > MAX_VAL)
			if (pthread_mutex_lock(&data.mutex) != 0 ||
					pthread_cond_signal(&data.cond_check) != 0 ||
					pthread_cond_wait(&data.cond_inc, &data.mutex) ||
					pthread_mutex_unlock(&data.mutex) != 0)
				return (EXIT_FAILURE);
	}
	pthread_cancel(thread_check);
	return (EXIT_SUCCESS);
}

Mad scientist a écrit:

Azuraul a écrit:

Je precise que mon processeur est un quadricoeurs donc si j' ai bien compris je gere vraiment 4 threads en paralele (c'est bien ca ?)

À peu près, sauf que dans ton cas tu as plein de synchronisations donc ton programme va juste être infiniment plus lent et n'exploitera pas plus d'un cœur à la fois.


Je me doute bien que dans ce cas c' est inutile, mais c'est pour me faire la main :) apres je me demande quand meme si c' est normal que mon CP monte a 44% d'utilisation avec une boucle de 1million?

Merci

-
Edité par Azuraul 22 novembre 2017 à 8:16:37

  • Partager sur Facebook
  • Partager sur Twitter
22 novembre 2017 à 9:18:52

Regarde la suite du lien que j'ai passé,il explique aussi ce soucis :D

-
Edité par neuneutrinos 22 novembre 2017 à 9:19:08

  • Partager sur Facebook
  • Partager sur Twitter