Comme je l'ai dis, je code en python, mais j'ai du me relancer dans du C pour pouvoir profiter du multi-threading.
Je suis plutôt novice alors garre à vos yeux ahah
J'ai réussi à faire une comparaison entre un code équivalent sur python (single-core à cause du GIL) et C (multi-threading) : La différence est réelle, je suis a 150s en C, contre environ 15 minutes côté Python, je suis conquis !
Mais voila, j'ai un petit soucis.
J'ai crée une fonction qui génère une certaine quantité de mot en fonction du nombre de lettre (le but étant de faire toutes les combinaisons possible) C'est probablement un "projet" aventureux, mais je compte bien le réussir.
Pour l'instant je n'en suis qu'au début, c'est donc pourquoi mon code n'est pas étoffé, et des combinaisons n'existes pas (en effet, je créé le mot en prenant des lettres au hasard, il y a donc un pourcentage de "perte" que j'évalue à +/- 10%)
Voici mon code :
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <math.h>
#define NUM_THREADS 5
char a[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\0";
t = 0;
p = 0;
w = 0;
int i = 0;
int ii = 0;
int p1, p2, p3, p4, p5;
FILE* dico = NULL;
int dictionnaire(way_of_file, mode, maxi)
{
char m[maxi + 2];
m[maxi] = '\n';
m[maxi + 1] = '\0';
int h = 0;
dico = fopen(way_of_file, mode);
if (dico != NULL)
{
for (i = 0 ; i < pow(strlen(a), maxi); i++)
{
for (ii = 0; ii < maxi; ii++)
{
h = rand() % strlen(a);
m[ii] = a[h];
}
fprintf(dico, m);
}
fclose(dico);
}
return 0;
}
int main()
{
i = 0;
printf("%d\n", t);
pthread_t threads[NUM_THREADS];
p1 = pthread_create(threads, NULL, dictionnaire("C:/Users/Flavien/Desktop/dictionnaire_C/dico1.txt", "w", 3), NULL);
p2 = pthread_create(threads, NULL, dictionnaire("C:/Users/Flavien/Desktop/dictionnaire_C/dico2.txt", "w", 4), NULL);
p3 = pthread_create(threads, NULL, dictionnaire("C:/Users/Flavien/Desktop/dictionnaire_C/dico3.txt", "w", 5), NULL);
p4 = pthread_create(threads, NULL, dictionnaire("C:/Users/Flavien/Desktop/dictionnaire_C/dico4.txt", "w", 6), NULL);
p5 = pthread_create(threads, NULL, dictionnaire("C:/Users/Flavien/Desktop/dictionnaire_C/dico5.txt", "w", 7), NULL);
}
Je sais que vos yeux vont probablement se dévitaliser et que vous aller faire un léger malaise, mais encore une fois je code en C très très rarement, d'où des fautes stupides, ou un code brouillon. Mon code fonctionnait relativement très bien jusqu'à maintenant (jusqu'au p3).
Mon but, comme je vous l'ai dis, étant de former des mots d'une longueur donnée, j'ai donc rajouter p4 (mots de 6 lettres) et p5(mots de 7lettres). Mais, lors du lancement, surprise, seulement dico1, dico2 et dico3 apparaissent dans mon dossier dictionnaire_C, et dico4 se lance seulement quand dico3 est fini, de même que dico5 se lance seulement quand dico4 est fini.
Ma question est donc, pourquoi dico1, 2 et 3 se lance en simultanés, mais dico4 et dico5 non. Un problème de charge processeur ?
Tant que j'y suis, je code sous Code_Blocks, je le trouve bien sous le gestionnaire de tache, mais il utilise casiment pas de charge cpu (8%)
Merci d'avance, encore une fois, de toute votre aide !
Flavien
EDIT : Mon code python tourne depuis environ 2 jours pour former les mots de 6 lettres. J'ai lancé mon code C il y a 10 minutes, il vient de le dépasser (le fichier où sont écris les mots, en, python fait 22Go, contre déjà 32Go pour le C. Soit je code mal, soit le C est vraiment un langage de fou !
strtlen(a) est une constante, mieux, pow(strlen(a),maxi) sont constantes dans chaque fonctions.
Donc dégage ça du for (qui recaculera tout ça à chaque itérations !)
au début de ta fonction dictionnaire, tu mets :
int len = strlen(a);
int p = pow(len,maxi);
puis ensuite dans tes for, tu ne manipules que des len et des p
A noter que le multithreading sur de l'acces disque ne sera pas forcément pertinent. Ton programme serait tout aussi rapide (ou presque) sans multithreading dans ton cas.
python est un langage interprété, donc beaucoup plus lent, alors que C est un langage compilé bien plus rapide.
Alors ce que tu écris est, exécute d'abord l'appek à dictionnaire et une fois l'appel terminé utilise la valeur de retour comme 3ème argument dans l'appel à pthread_create.
Du coup tu pense que «Mais, lors du lancement, surprise, seulement dico1, dico2 et dico3 apparaissent dans mon dossier dictionnaire_C, et dico4 se lance seulement quand dico3 est fini, de même que dico5 se lance seulement quand dico4 est fini.» est anormal alors que pas du tout.
Le prototype de pthread_create t'indique que tu dois donner en 3ème paramètre une fonction qui renvoie un void * et qui prend un unique paramètre de type void *, cet argument sera transmit à ta fonction par pthread_create et c'est le 4ème paramètre.
tu devras donc (par souci de simplicité) créer une structure qui te permettra de passer tout ce que tu veux à ta fonction →
typedef struct {
char *path;
int mode;
int max;
} routine_param_t;
ta fonction devra ressembler à
void *parallel_routine(void *arg)
{
// on transtype sauvagement mais on sait pourquoi
routine_param_t *param = (routine_param_t *) arg;
for(int i=0; i<param->max; i++) {
...
}
Ici, j'envoie en 3eme paramètre une fonction Int et non void, et en plus de ça, je lui donne des paramètre. Et en paramètre 4, j'envoie NULL alors que c'est ici que je devrais envoyer les paramètre de ma fonction Void ?
Pour la structure, je me rappelais vaguement de ce que c'est, je viens juste d'y jeter un coup d'oeil (tuto OC) ! Du coup, peux tu m'expliquer 2 trucs :
void *parallel_routine(void *arg)
{
// on transtype sauvagement mais on sait pourquoi
routine_param_t *param = (routine_param_t *) arg;
for(int i=0; i<param->max; i++) {
...
}
Cette fonction et plus particulièrement cette ligne :
routine_param_t *param = (routine_param_t *) arg;
On créer un pointeur "param" du type de notre structure. Mais que signifie ce qui se trouve à droite du égal ? Et pour la boucle for :
for(int i=0; i<param->max; i++)
J'avais jamais vu cette écriture : "i<param->max". Je le lis donc i inférieur à param, et on lui affecte la valeur max ?
Cette fonction et plus particulièrement cette ligne :
routine_param_t *param = (routine_param_t *) arg;
On créer un pointeur "param" du type de notre structure. Mais que signifie ce qui se trouve à droite du égal ?
Alors c'est du C de base. Je t'imagine que très peu à l'aise avec les pointeurs.
Cette ligne, comme le signale le commentaire, transtype (réinterprète) le paramètre arg qui est un pointeur sur void (un pointeur générique) en un pointeur sur une structure de type routine_param_t.
Si tu as du mal avec ces notions, il va falloir reprendre le C au niveau des pointeurs parce que ça ne fera que s'empirer par la suite.
FunlY-Fla a écrit:
J'ai réussi à faire une comparaison entre un code équivalent sur python (single-core à cause du GIL) et C (multi-threading) : La différence est réelle, je suis a 150s en C, contre environ 15 minutes côté Python, je suis conquis !
Comme le dit très bien FVirtMan, Python c'est interprété alors C est compilé.
Mais pourquoi n'essayes-tu donc pas de le faire en Julia ?
Ce sera tellement plus simple si tu viens de python, et quasiment avec des performances à la C … → https://julialang.org/
Bon faudra quand même utiliser google pour la doc, même pour Julia 🙂
Si tu persistes à vouloir le faire en C, nous pourrons continuer à t'aider, mais bon, tu pars de loin.
Edit:
FunlY-Fla a écrit:
rouloude a écrit:
int dictionnaire(way_of_file, mode, maxi)
Et les type des paramètres, il sont où ?
Eh bien justement, si je met "char way_of_file" ca plante...
En effet, passe à Julia, ou prends le temps d'apprendre C avant de vouloir te lancer dans un projet de cet envergure.
Cette fonction et plus particulièrement cette ligne :
routine_param_t *param = (routine_param_t *) arg;
On créer un pointeur "param" du type de notre structure. Mais que signifie ce qui se trouve à droite du égal ?
Alors c'est du C de base. Je t'imagine que très peu à l'aise avec les pointeurs.
Cette ligne, comme le signale le commentaire, transtype (réinterprète) le paramètre arg qui est un pointeur sur void (un pointeur générique) en un pointeur sur une structure de type routine_param_t.
Si tu as du mal avec ces notions, il va falloir reprendre le C au niveau des pointeurs parce que ça ne fera que s'empirer par la suite.
En effet, c'était pas sorcier a comprendre, autant pour moi
En fait cest pas si compliqué que ca à comprendre si on se concentre 10min, j'ai pas forcement de soucis à lire un code, mais plutot à l'écrire... embetant n'est-ce pas ?
Autant arreter le carnage de suite, sinon vous aller très souvent me retrouver sur le forum en demandant de l'aide, il faudrait que je prenne du temps pour me mettre au C, et avec les cours j'ai pas vraiment la foie, même si j'avais déjà suivi le tuto OC presque en entier (je sais, on dirait pas ahah)
Je vais donc aller voir pour Julia, en espérant être moins désespérant
Merci encore de toute votre aide,
Passez tous une excellente journée,
Flavien
EDIT :
Finalement, après réflexion, je vais me lancer dans le C.
Ca ne pourra m'être que bénéfique. Je promet (enfin j'essaierai) de ne revenir sur le forum, que pour des bonnes raisons (mais vu votre niveau en C...)
Finalement, après réflexion, je vais me lancer dans le C.
Ca ne pourra m'être que bénéfique. Je promet (enfin j'essaierai) de ne revenir sur le forum, que pour des bonnes raisons (mais vu votre niveau en C...)
Bien le C, et tu trouveras ici des réponses aux questions simples comme aux compliquées.
Allez, pour commencer, un petit correctif à ton programme:
Soyons précis : il s'agit du '\0', pas du "\0". (*)
Comme l'a dit Marc Mongenet, le '\0' se met automatiquement en fin de chaîne dans une chaîne littérale, c'est-à-dire une chaîne de caractères écrite explicitement avec des guillemets :
char t3[] = "abc"; // ceci remplit un tableau de 4 caractères {'a', 'b', 'c', '\0'}
Il me semble que c'est le seul cas.
----------
(*) "\0" contient trois caractères : {'\\', '0', '\0'}.
Mais du coup, quand est-ce que "\0" se met automatiquement à la fin d'une chaine de caractere ?
Quand on utilise la notation de chaine de caractères, avec les guillemets.
Multi-threading
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html
Et les type des paramètres, il sont où ?