Tableaux croisés

mslider Messages postés 109 Date d'inscription jeudi 21 octobre 2004 Statut Membre Dernière intervention 7 mars 2010 - 25 janv. 2010 à 12:30
tpoinsot Messages postés 345 Date d'inscription mardi 1 juin 2004 Statut Membre Dernière intervention 17 octobre 2014 - 25 févr. 2010 à 16:23
--Bonjour à tous et toutes,

j'ai un problème à résoudre en C ou C++, je l'ai en partie résolu pour une petite quantité de
données, mais çà plante dès que la taille du fichier augmente.
Il s'agit de construire des tableaux croisés (ou table pivot)

Voilà un exemple:

contenu du fichier texte à traiter (ce n'est qu'un echantillon):

librairies etiquettes scores
GSM1 AAAAAAAAAA 17
GSM1 AAAAAAATCA 1
GSM1 AAAAAAATTT 1
GSM1 AAAAACAAAA 1
GSM10419 AAAAAAAAAA 54
GSM10419 AAAAAAAAAC 2
GSM10419 AAAAAACTAC 1
GSM10419 AAAAAACTCC 2
GSM10419 AAAAAACTGA 1
GSM10419 AAAAAAGAAA 3
GSM10419 AAAAAAGGCA 14
GSM10424 AAAAACATAG 1
GSM10424 AAAAACATCC 1
GSM10424 AAAAACCAAA 1
GSM10424 AAAAACCTAC 1
GSM10425 AAAAAAAAAA 15
GSM10425 AAAAAAAAAG 2
GSM10425 AAAAAAAAAT 1
GSM10425 AAAAAAAGAA 1
GSM10425 AAAAAAAGAG 4

format du fichier resultat a obtenir apres traitement:

etiquettes GSM1 GSM10419 GSM10424 GSM10425
AAAAAAAAAA 17 54 0 15
AAAAAAAAAC 0 2 0 0
AAAAAAAAAG 0 0 0 2
AAAAAAAAAT 0 0 0 1
AAAAAAAGAA 0 0 0 1
AAAAAAAGAG 0 0 0 4
AAAAAAATCA 1 0 0 0
AAAAAAATTT 1 0 0 0
AAAAAACTAC 0 1 0 0
AAAAAACTCC 0 2 0 0
AAAAAACTGA 0 1 0 0
AAAAAAGAAA 0 3 0 0
AAAAAAGGCA 0 14 0 0
AAAAACAAAA 1 0 0 0
AAAAACATAG 0 0 1 0
AAAAACATCC 0 0 1 0
AAAAACCAAA 0 0 1 0
AAAAACCTAC 0 0 1 0

je travaille sur une machine 64 bits, donc écrire du code 64 bits serait une optimisation.
Si quelqu'un a déjà eu ce genre de problème à traiter, un petit coup de pouce serait le bienvenu, merci.

142 réponses

mslider Messages postés 109 Date d'inscription jeudi 21 octobre 2004 Statut Membre Dernière intervention 7 mars 2010
28 janv. 2010 à 11:15
je pense que l'on pourrait optimiser en stockant tout en mémoire sans passer par un fichier temporaire.
De la ram j'en ai, voilà ma machine:

HP ProLiant 64bits DL585-G2:
- CPU: 4x Dual-Core AMD Opteron Processor 8216 @ 2400MHz
- Memory: 64GB RAM
- OS: Linux Redhat / CentOS release 4.6 (Final)
- Kernel: 2.6.9-67.0.4.EL
- gcc version 3.4.6


mslider
0
mslider Messages postés 109 Date d'inscription jeudi 21 octobre 2004 Statut Membre Dernière intervention 7 mars 2010
28 janv. 2010 à 12:36
j'ai des bugs à la compilation:

thip.c: In function 'findOrAddArray':
thip.c:29: warning: incompatible implicit declaration of built-in function 'malloc'
thip.c:30: warning: incompatible implicit declaration of built-in function 'strlen'
thip.c:31: warning: incompatible implicit declaration of built-in function 'strcpy'
thip.c:37: warning: incompatible implicit declaration of built-in function 'malloc'
thip.c:39: warning: incompatible implicit declaration of built-in function 'memcpy'
thip.c:40: warning: incompatible implicit declaration of built-in function 'strlen'
thip.c:41: warning: incompatible implicit declaration of built-in function 'strcpy'
thip.c:44: warning: incompatible implicit declaration of built-in function 'free'
thip.c:49: warning: incompatible implicit declaration of built-in function 'malloc'
thip.c:51: warning: incompatible implicit declaration of built-in function 'memcpy'
thip.c:52: warning: incompatible implicit declaration of built-in function 'strlen'
thip.c:53: warning: incompatible implicit declaration of built-in function 'strcpy'
thip.c:56: warning: incompatible implicit declaration of built-in function 'free'
thip.c: In function 'main':
thip.c:95: warning: incompatible implicit declaration of built-in function 'malloc'
thip.c:124: warning: incompatible implicit declaration of built-in function 'free'
thip.c:126: error: incompatible type for argument 1 of 'free'
thip.c:128: error: incompatible type for argument 1 of 'free'
0
mslider Messages postés 109 Date d'inscription jeudi 21 octobre 2004 Statut Membre Dernière intervention 7 mars 2010
28 janv. 2010 à 13:17
bon tout est OK
çà compile bien, çà venait du copier/coller de Windows à Unix.
j'ai rajouté quelque truc dans le main au niveau du controle du fichier d'entrée:
#include <stdio.h>

typedef struct {
char **array;
int size;
int allocSize;
} ARR;

int findOrAddArray(char *item, ARR *arr)
{
int i, k;
int g 0, d arr->size-1;

while ( g <= d ) {
i = (g+d)/2;
k = strcmp(item, arr->array[i]);
if ( k == 0 )
return i;
if ( k < 0 )
d = i-1;
else
g = i+1;
}
i = g;

char ** p;
if ( arr->size == 0 )
{
p  = (char **) malloc(sizeof(char *)*arr->allocSize);
p[0] = malloc(strlen(item)+1);
strcpy(p[0], item);
arr->array = p;
}
else if ( arr->size == arr->allocSize )
{
arr->allocSize *= 2;
p  = (char **) malloc(sizeof(char *)*arr->allocSize);
if ( i > 0 )
memcpy(p, arr->array, sizeof(char *)*i);
p[i] = malloc(strlen(item)+1);
strcpy(p[i], item);
if ( i < arr->size )
memcpy(&p[i+1], &arr->array[i], sizeof(char *)*(arr->size-i));
free(arr->array);
arr->array = p;
}
else
{
p  = (char **) malloc(sizeof(char *)*arr->allocSize);
if ( i > 0 )
memcpy(p, arr->array, sizeof(char *)*i);
p[i] = malloc(strlen(item)+1);
strcpy(p[i], item);
if ( i < arr->size )
memcpy(&p[i+1], &arr->array[i], sizeof(char *)*(arr->size-i));
free(arr->array);
arr->array = p;
}
arr->size++;
return i;
}

main(int argc, char *argv[])
{
    if(argc!=2)
    {
     printf("Il manque un nom de fichier en argument ! \n");
     return 1;
    }
FILE *fp, *fpo;
ARR tag;
ARR gsm;

tag.size = 0;
tag.allocSize = 2000;
gsm.size = 0;
gsm.allocSize = 500;

char bufTag[512], bufGsm[512];
char prevTag[512];
int freq;
int i, j;

fp = fopen(argv[1],"r");
if(fp == NULL)
 {
        printf("Cant open %s \n", argv[1]);
        return 2;
     }
fpo = fopen("xxxx", "w");
prevTag[0] = 0;
while ( !feof(fp) )
{
if ( fscanf(fp, "%s %s %d", bufGsm, bufTag, &freq) == 3 )
{
i = findOrAddArray(bufTag, &tag);
j = findOrAddArray(bufGsm, &gsm);
fprintf(fpo, "%d %d %d\n", i, j, freq);
}

}
fclose(fp);
fclose(fpo);

int *res = (int*)malloc(tag.size*gsm.size*sizeof(int));
fp = fopen("xxxx","r"); /* temporaire */
while ( !feof(fp) )
{
if ( fscanf(fp, "%d %d %d", &i, &j, &freq) == 3 )
{
res[i*gsm.size+j] = freq;
}
}
fclose(fp);

fpo = stdout;

fprintf(fpo, "etiquette");
for (j=0; j<gsm.size; j++)
{
fprintf(fpo, " %s", gsm.array[j]);
}
fprintf(fpo, "\n");

for (i=0; i<tag.size; i++)
{
fprintf(fpo, "%s", tag.array[i]);
for (j=0; j<gsm.size; j++)
{
fprintf(fpo, " %d", res[i*gsm.size+j]);
}
fprintf(fpo, "\n");
}
free(res);
for (i=0; i<tag.size; i++) free(tag.array[i]);
free(tag);
for (i=0; i<gsm.size; i++) free(gsm.array[i]);
free(gsm);
}



un test sur le fichier sample.txt donne:

ton code C: 0.078u 0.018s 0:05.27 1.5% 0+0k 0+0io 0pf+0w
mon AWK: 1.254u 0.019s 0:03.17 39.7% 0+0k 0+0io 0pf+0w

je lance un test sur le gros fichier pour le fun
0
tpoinsot Messages postés 345 Date d'inscription mardi 1 juin 2004 Statut Membre Dernière intervention 17 octobre 2014 4
28 janv. 2010 à 18:34
Les erreurs de compilation provenaient essentiellement des includes manquant.

Voici une version avec :
- les controles et le passage du fichier en argument.
- plus conservatipon de la derniere recherche au cas ou on redemande la même 2 fois de suite (quand c'est déjà trié ça va un chouïa plus vite).
- les free() de la fin étaient faux
- l'affichage du % de lecture du fichier en entrée pour suivre.

Sur ma grosse bête (Pentium 500 MHz, RAM 256Mo, si si ! )
wc -l sur ton big_file = 35 mn (très big, le file !)
traitement estimé à 67h (1% en 40 mn), je ne vais pas au bout bien entendu.

Ton bourrin doit être un poil plus rapide.

Pour faire mieux :
- ne pas utiliser le fichier intermédiaire (attention de ne pas lancer 2 fois le prog en concurrence), mais je ne connais les dimensions qu'à la fin
- améliorer la recherche des index dans le tableau trié

sinon, tu peux aussi "spliter" le big file et lancer le programme sur chaque morceau, ça doit être + rapide et ne changerai rien à l'intégration à une base.

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
char **array;
int size;
int allocSize;
int lastIndex;
char * lastFind;
} ARR;

void initArray(ARR* a, int sz)
{
a->size = 0;
a->allocSize = sz;
a->array = (char **) malloc(sizeof(char *) * sz);
a->lastIndex = -1;
a->lastFind = (char *)0;
}

int findOrAddArray(ARR *arr, char *item)
{
if ( arr->lastFind && !strcmp(item, arr->lastFind) )
return arr->lastIndex;

int i, k;
int g 0, d arr->size-1;

while ( g <= d ) {
i = (g+d)/2;
k = strcmp(item, arr->array[i]);
if ( k == 0 ) {
arr->lastFind = arr->array[i];
arr->lastIndex = i;
return i;
}
if ( k < 0 )
d = i-1;
else
g = i+1;

}
i = g;

if ( arr->size == arr->allocSize )
arr->allocSize *= 2;
char ** p  = (char **) malloc(sizeof(char *) * arr->allocSize);

if ( i > 0 )
memcpy(p, arr->array, sizeof(char *) * i);

p[i] = malloc(strlen(item) + 1);
strcpy(p[i], item);

if ( i < arr->size )
memcpy(&p[i+1], &arr->array[i], sizeof(char *) * (arr->size-i));

free(arr->array);
arr->array = p;

arr->size++;
arr->lastFind = arr->array[i];
arr->lastIndex = g;
return i;
}

main(int argc, char *argv[])
{
FILE *fp, *fpo;
ARR tag;
ARR gsm;
initArray(&tag, 2000);
initArray(&gsm, 500);

if ( argc != 2 )
{
fprintf(stderr, "il manque le fichier à traiter.");
exit(1);
}

char bufTag[512], bufGsm[512];
int freq;
int i, j;

if ( !(fp = fopen(argv[1],"r")) ) 
{
fprintf(stderr, "%s: erreur d'ouverture");
exit(1);
}
struct stat st;
stat(argv[1], &st);
long fsz = st.st_size;
fprintf(stderr, "size = %d\n", fsz);

fpo = fopen("xxxx", "w");
int n = 1;
while ( !feof(fp) )
{
if ( fscanf(fp, "%s %s %d", bufGsm, bufTag, &freq) == 3 )
{
i = findOrAddArray(&tag, bufTag);
j = findOrAddArray(&gsm, bufGsm);
fprintf(fpo, "%d %d %d\n", i, j, freq);
}
if ( fsz > 0 && ftell(fp)*100.0/fsz > n )
{
fprintf(stderr, "%d %%\r", n++);
fflush(stderr);
}
}
fprintf(stderr, "100 %%\n");
fclose(fp);
fclose(fpo);

/*************************************/
int *res = (int*)malloc(tag.size * gsm.size * sizeof(int));
fp = fopen("xxxx","r");
while ( !feof(fp) ) 
{
if ( fscanf(fp, "%d %d %d", &i, &j, &freq) == 3 )
res[i*gsm.size+j] = freq;
}
fclose(fp);

/*************************************/
fpo = stdout;

fprintf(fpo, "etiquette");
for (j=0; j<gsm.size; j++)
fprintf(fpo, " %s", gsm.array[j]);
fprintf(fpo, "\n");

for (i=0; i<tag.size; i++)
{
fprintf(fpo, "%s", tag.array[i]);
for (j=0; j<gsm.size; j++)
fprintf(fpo, " %d", res[i*gsm.size+j]);
fprintf(fpo, "\n");
}
for (i=0; i<tag.size; i++) free(tag.array[i]);
free(tag.array);
for (i=0; i<gsm.size; i++) free(gsm.array[i]);
free(gsm.array);
free(res);
}



thip
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
mslider Messages postés 109 Date d'inscription jeudi 21 octobre 2004 Statut Membre Dernière intervention 7 mars 2010
29 janv. 2010 à 10:08
après un test sur le fichier sample.txt, on dirait que çà se vaut:

mon code AWK: real 8.53, user 1.27, sys 0.02
ton dernier code C: real 10.47, user 0.07, sys 0.02

Tu peux optimiser largement ton code(enfin je pense) en évitant de passer par ce fichier temporaire(xxxx), le programme perd du temps en accès lecture/écriture à ce niveau.
Pourquoi ne pas stocker ce résultat non pas dans un fichier mais en RAM ? Ma bécane possède 64Go de RAM, à y être autant mapper le fichier d'entrée directement en RAM.

Autre optimisation: le multi-thread, utiliser une dichotomie ou un pivot et envoyer le traitement d'un premier lot de données au proc1 et un deuxième lot au proc2 (dans le cas où on utiliserait 2 proc).

mslider
0
tpoinsot Messages postés 345 Date d'inscription mardi 1 juin 2004 Statut Membre Dernière intervention 17 octobre 2014 4
29 janv. 2010 à 10:53
ok mais pour la recherche c'est une dichotomie (je crois me souvenir que c'est plus rapide par tiers plutôt que par moitié : je vais vérifier), au le fork() n'apporte rien car on ne connait les dimensions de res qu'en fin de parcours. Ou alors on reviens à la première idée de parcourir 2 fois le fichier, la première permettant de connaitre les dimensions : on fork et les 2 processus connaissent ces valeurs.

Sur ta machine, essaie donc de voir le surcoût de l'écriture en ne conservant que les 2 appels à findOrAddArray().

			i = findOrAddArray(&tag, bufTag);
j = findOrAddArray(&gsm, bufGsm);
// fprintf(fpo, "%d %d %d\n", i, j, freq);
...
/*
        int *res = (int*)malloc(tag.size * gsm.size * sizeof(int));
fp = fopen("xxxx","r");
while ( !feof(fp) ) 
{
if ( fscanf(fp, "%d %d %d", &i, &j, &freq) == 3 )
res[i*gsm.size+j] = freq;
}
fclose(fp);
...
        jusque là, attention aux commentaires intérieurs
*/
for (i=0; i<tag.size; i++) free(tag.array[i]);
free(tag.array);
for (i=0; i<gsm.size; i++) free(gsm.array[i]);
free(gsm.array);
free(res);
}


et puis tu peux grouper les E/S en mettant un gros buffer sur l'un des 2 fichiers avec setvbuf(), un buffer de 10 ou 100Mo je sais pas trop ce qui est le mieux.
thip
0
mslider Messages postés 109 Date d'inscription jeudi 21 octobre 2004 Statut Membre Dernière intervention 7 mars 2010
29 janv. 2010 à 14:28
avec écriture:
real 10.93
user 0.07
sys 0.02

sans écriture:
real 0.01
user 0.00
sys 0.00

ya pas photo, faut virer ce passage par ce fichier de stockage et mettre un setvbuf() de 100 Mo.
0
tpoinsot Messages postés 345 Date d'inscription mardi 1 juin 2004 Statut Membre Dernière intervention 17 octobre 2014 4
29 janv. 2010 à 16:10
ensuite retire les findOrAddArray, tu n'auras plus que la lecture !
la recherche binaire n'est pas adaptée à big_file.txt : trop de tag.
il faut un hash...
mais je ne pense plus que le temporaire soit réellement pénalisant.

Ou alors, splite le fichier en entrée. Ce n'est pas possible ?

thip
0
mslider Messages postés 109 Date d'inscription jeudi 21 octobre 2004 Statut Membre Dernière intervention 7 mars 2010
29 janv. 2010 à 17:14
si je retire les findOrAddArray ya plus rien qui marche.
impossible de splitter le fichier en entrée, la construction de la matrice utilise obligatoirement le fichier entier sinon rien.
0
tpoinsot Messages postés 345 Date d'inscription mardi 1 juin 2004 Statut Membre Dernière intervention 17 octobre 2014 4
29 janv. 2010 à 18:50
bien sûr que ça ne marche plus, l'idée étant de se rendre compte que la fonction est lente, et l'usage de xxxx pas tant que ça.
Mon estimation de 67h pour la constitution de xxxx tombe à 1h avec un hash.

thip
0
mslider Messages postés 109 Date d'inscription jeudi 21 octobre 2004 Statut Membre Dernière intervention 7 mars 2010
29 janv. 2010 à 21:13
ben au vue des temps l'utilisation du fichier temporaire ralenti un peu le traitement.
Et puis logiquement il est plus rapide d'accéder à la mémoive qu'à la lecture/écriture d'un fichier. Donc pourquoi ne pas utiliser un hash en mémoire vive et éviter le stockage de valeurs dans un fichier ?

mslider
0
tpoinsot Messages postés 345 Date d'inscription mardi 1 juin 2004 Statut Membre Dernière intervention 17 octobre 2014 4
29 janv. 2010 à 23:28
parce que j'ai du mal à me rendre compte ce que font 60 millions de malloc et que je suis alors tenté de réduire comme je l'ai fait pour les tag et gsm et que je suis persuadé qu'il y a mieux mais je n'ai pas encore trouvé quoi. Je me fie à mon instinct qui me dit qu'il y à quelque chose d'autre mais je ne sais pas encore quoi.

De toute façon, pour moi les fprintf/fscanf ne sont qu'un prélude au pipe+fork. Je pense toujours que cette partie est marginale. c'est le début (lecture et mise en forme) qui bouffe toute la cpu.


thip
0
tpoinsot Messages postés 345 Date d'inscription mardi 1 juin 2004 Statut Membre Dernière intervention 17 octobre 2014 4
30 janv. 2010 à 11:33
Finalement, je n'ai pas aimé le fork et j'ai mis une pile.

Pour le hash, il faut télécharger 3 fichiers sur ce lien :
- hashtable.c
- hashtable.h
- hashtable_private.h

et ajouter -lm à la compilation

Pour le code (toujours un seul fichier mais ça devient lourd) :

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hashtable.h"


typedef struct {
char **array;
int size;
int allocSize;
struct hashtable *h;
} ARR;

typedef struct {
long i;
long j;
long freq;
} FREQ;

typedef struct st_bloc {
FREQ tbfreq[1024];
int n;
struct st_bloc *next;
} BLOC;


static unsigned int hashKey(void* item)
{
unsigned int h = 0;
char *p = (char *)item;
while ( *p ) {
h = ((h << 5) + h) + *p++;
}
return h;
}

static int compareKey(void* k1, void* k2)
{
return !strcmp(k1, k2);
}


void initArray(ARR* a, int sz, int hsz)
{
a->size = 0;
a->allocSize = sz;
a->array = (char **) malloc(sizeof(char *) * sz);
a->h = create_hashtable(hsz, hashKey, compareKey);
}

long findOrAddArray(ARR *arr, char *item)
{
long * pi = (long *)hashtable_search(arr->h, item);
if ( pi )
{
return *pi;
}

long i = arr->size;
int n = strlen(item);
char * key = malloc(n + 1 + sizeof(long));
strcpy(key, item);

pi = (long *)(&key[n + 1]);
*pi = i;

if ( arr->size == arr->allocSize ) {
arr->allocSize *= 2;
char ** p  = (char **) malloc(sizeof(char *) * arr->allocSize);
memcpy(p, arr->array, sizeof(char *) * arr->size);
free(arr->array);
arr->array = p;
}
arr->array[i] = key;
arr->size++;
hashtable_insert(arr->h, key, pi);
return i;
}

BLOC* empile(BLOC *b, long i, long j, long freq)
{
if ( !b ) {
b = (BLOC *)malloc(sizeof(BLOC));
b->n = 0;
b->next = 0;
}
else if ( b->n == sizeof(b->tbfreq)/sizeof(FREQ) ) {
BLOC *x = b;
b = (BLOC *)malloc(sizeof(BLOC));
b->next = x;
b->n = 0;
}
FREQ* pf = &b->tbfreq[ b->n++ ];
pf->i = i;
pf->j = j;
pf->freq = freq;
return b;
}

BLOC* depile(BLOC *b, long *i, long *j, long * freq)
{
if ( !b ) return NULL;

if ( b->n > 0 ) {
FREQ* pf = &b->tbfreq[ --b->n ];
*i = pf->i;
*j = pf->j;
*freq = pf->freq;
}
else {
BLOC *x = b->next;
free(b);
b = depile(x, i, j, freq);
}
return b;
}

main(int argc, char *argv[])
{
BLOC *blk = NULL;
FILE *fp;
ARR tag;
ARR gsm;
initArray(&tag, 10000, 1000000);
initArray(&gsm, 500, 1000);

if ( argc != 2 )
{
fprintf(stderr, "il manque le fichier à traiter.");
exit(1);
}

char bufTag[512], bufGsm[512];
long freq;
long i, j;

if ( !(fp = fopen(argv[1],"r")) ) 
{
fprintf(stderr, "%s: erreur d'ouverture");
exit(1);
}
struct stat st;
stat(argv[1], &st);
long fsz = st.st_size;
fprintf(stderr, "size = %d\n", fsz);

float n = 0.1;
while ( !feof(fp) )
{
if ( fscanf(fp, "%s %s %d", bufGsm, bufTag, &freq) == 3 )
{
i = findOrAddArray(&tag, bufTag);
j = findOrAddArray(&gsm, bufGsm);
blk = empile(blk, i, j, freq);
}
if ( fsz > 0 && ftell(fp)*100.0/fsz > n )
{
fprintf(stderr, "%.1f%% tag:%d gsm:%d\r", n,tag.size,gsm.size);
fflush(stderr);
n += 0.1;
}
}
fprintf(stderr, "100.0%% tag:%d gsm:%d\r", tag.size,gsm.size);
fclose(fp);

/*************************************/
long *res = (long*)malloc(tag.size * gsm.size * sizeof(long));
while ( blk = depile(blk, &i, &j, &freq) )
res[i*gsm.size+j] = freq;

/*************************************/
FILE *fpo = stdout;

fprintf(fpo, "etiquette");
for (j=0; j<gsm.size; j++)
fprintf(fpo, " %s", gsm.array[j]);
fprintf(fpo, "\n");

for (i=0; i<tag.size; i++)
{
fprintf(fpo, "%s", tag.array[i]);
for (j=0; j<gsm.size; j++)
fprintf(fpo, " %d", res[i*gsm.size+j]);
fprintf(fpo, "\n");
}
hashtable_destroy(tag.h, 0);
free(tag.array);
hashtable_destroy(gsm.h, 0);
free(gsm.array);
free(res);
}


Sur ma machine, tout va bien jusqu'à 15% après elle swape et c'est mort. Comme tu as de la mémoire, ce doit être mieux pour toi.

thip
0
mslider Messages postés 109 Date d'inscription jeudi 21 octobre 2004 Statut Membre Dernière intervention 7 mars 2010
30 janv. 2010 à 17:36
petit souci à la compilation:

gcc -m64 -O2 thip_hash.c -lm

/tmp/ccyRjrx6.o(.text+0x8f): In function `initArray':
: undefined reference to `create_hashtable'
/tmp/ccyRjrx6.o(.text+0xd8): In function `findOrAddArray':
: undefined reference to `hashtable_search'
/tmp/ccyRjrx6.o(.text+0x15f): In function `findOrAddArray':
: undefined reference to `hashtable_insert'
/tmp/ccyRjrx6.o(.text+0x641): In function `main':
: undefined reference to `hashtable_destroy'
/tmp/ccyRjrx6.o(.text+0x65d): In function `main':
: undefined reference to `hashtable_destroy'
collect2: ld returned 1 exit status
0
tpoinsot Messages postés 345 Date d'inscription mardi 1 juin 2004 Statut Membre Dernière intervention 17 octobre 2014 4
31 janv. 2010 à 16:27
as-tu bien téléchargé les 3 fichiers ?
ensuite pense à compiler du style gcc -o -m64 -O2 -ml tonExe thip.c hashtable.c, en ajoutant au passage l'option de threads avec le nombre de coeurs de ton proc
ça ira beaucoup mieux.

thip
0
mslider Messages postés 109 Date d'inscription jeudi 21 octobre 2004 Statut Membre Dernière intervention 7 mars 2010
1 févr. 2010 à 11:09
pour pouvoir utiliser l'option de threads à la compilation du style:
gcc -o -m64 -O2 -ml tonExe thread2 -g -D_REENTRANT -D_GNU_SOURCE thip.c -lpthread
encore faut il avoir un code qui fasse appel à un #include dans l'entête, hors ce n'est pas le cas.

En revanche gcc -o -O2 -m64 thip.c hashtable.c -lm a bien créer un executable.

voilà le test sur sample.txt:

ton code C:
real 3.08
user 0.07
sys 0.04

code AWK:
real 3.10
user 1.24
sys 0.04

Test sur le big file:
time wc -l bigfile.txt

58859592 bigfile.txt
2.140u 1.849s 0:03.99 99.7%

time ./thip bigfile.txt
size = 1595586743
100.0% tag:18270900 gsm:1597
Segmentation fault (core dumped)

dommage la lecture du fichier était rapide.
0
tpoinsot Messages postés 345 Date d'inscription mardi 1 juin 2004 Statut Membre Dernière intervention 17 octobre 2014 4
1 févr. 2010 à 11:15
j'avais mal écris la commande, c'est "-o tonExe" pour obtenir l'exécutable "tonExe"

Sur sample.txt, awk ou c seront toujours +/- équivalents.

Bizarre ce seg fault. Après la lecture du fichier donc. je regarde.

thip
0
mslider Messages postés 109 Date d'inscription jeudi 21 octobre 2004 Statut Membre Dernière intervention 7 mars 2010
1 févr. 2010 à 12:08
oui après la lecture.

j'ai gonfflé les valeurs :

initArray(&tag, 20000, 2000000);
initArray(&gsm, 1000, 2000);

mais kif kif.
j'ai essayé de compilé en 32bits et sur une autre machine, la lecture est plus lente, çà arrive au bout
qd même et çà plante en seg fault.

mslider
0
tpoinsot Messages postés 345 Date d'inscription mardi 1 juin 2004 Statut Membre Dernière intervention 17 octobre 2014 4
1 févr. 2010 à 13:19
Ce ne sont pas les tableaux gsm/tag qui plantent, car ils ne servent qu'à la lecture : après, on a juste besoin du size.

Ajoute des fprintf(stderr, ...) pour voir où ça s'arrête : après malloc de res, pendant son remplissage, ou pendant la sortie des résultats.

thip
0
tpoinsot Messages postés 345 Date d'inscription mardi 1 juin 2004 Statut Membre Dernière intervention 17 octobre 2014 4
1 févr. 2010 à 14:32
le malloc est trop grand : remplace l'allocation de res.

/*************************************/
//long *res = (long*)malloc(tag.size * gsm.size * sizeof(long));
long **res = (long **)calloc(tag.size, sizeof(long *));
for (i = 0; i < tag.size; i++)
{
res[i] = (long *)calloc(gsm.size, sizeof(long));
}

while ( blk = depile(blk, &i, &j, &freq) )
res[i][j] = freq;

/*************************************/


puis l'utilisation
		for (j=0; j<gsm.size; j++)
fprintf(fpo, " %d", res[i][j]);


et enfin la libération
	for (i = 0; i < tag.size; i++)
free(res[i]);
free(res);

thip
0
Rejoignez-nous