Comportement de boucle très lentJ'ai une question concernant le temps passé en boucles.
J'analyse de plus grandes quantités de données de production, généralement 1 million de lignes.
Pour chaque ligne, la production capture le statut (colonne Statusnummer).
Si le statut est "1", alors je voudrais calculer les valeurs réelles ("ist") et définies ("soll").
Je dois donc calculer 1 million de lignes. Je fais cela plusieurs fois dans mon code, pour différentes valeurs.
Parfois, les boucles sont rapides (60 secondes), parfois très (!) lentes (plus d'une journée ! Le processeur fonctionne toujours à pleine charge !).
Toutes les colonnes sont définies sur numériques et continues, mais je n'arrive pas à comprendre pourquoi certaines boucles sont très lentes.
J'ai même vérifié si la cellule contient des valeurs manquantes (voir exemple de code) ; Pourtant, le code reste lent.
Une idée de ce que je fais de mal ?
Martre
Exemple de code lent :
for(i=1,i<=NRows(dt),i++,(
if(dt:Statusnummer[i] == 1,(
if(!isMissing(dt:Drehzahl[i]) & !isMissing(dt:geschw[i]) ,(
ist = dt:Drehzahl[i];
soll = dt:SollDrehzahl[i];
dt:Soll_drehzahl[i] = soll;
dt:Ist_drehzahl[i] = ist;
dt:Maschinenleistung[i] = 100*ist/soll;
));
));
));
Re : Comportement de boucle très lent@vince_faller Cool! Je ne vois qu'environ 10 fois plus rapide (ce qui est quand même assez étonnant.) Je soupçonne que cette accélération n'est pas liée au début/fin de la mise à jour des données, mais je pense également que les affectations matricielles feront quelque chose comme la mise à jour des données de début/fin en interne.
@EvanMcCorkle
Re : Comportement de boucle très lentMerci, probablement (voir commentaire ci-dessus, le problème a disparu entre-temps), c'était la raison, puisque de nombreux rapports étaient ouverts. Mais je ne peux pas reproduire pour le moment. Je vais présenter votre solution dans mon code et voir si c'est le correctif permanent.
MartreRe : Comportement de boucle très lentMise à jour : J'ai ajouté la méthode get rows which pour trouver les lignes.Évidemment, cela a la restriction d'exiger des données numériques, mais je parviens parfois à contourner ce problème.
Je suis un grand fan de tout faire avec des matrices.
Names default to here(1);
dt = New Table("Test",
Add Rows(1000000),
New Column("Statusnummer", Set Each Value(Random Integer(0, 1))),
New Column("Drehzahl", Set Each Value(Choose(Random Integer(1, 2), ., Random Normal()))),
New Column("geschw", Set Each Value(Choose(Random Integer(1, 2), ., Random Normal()))),
New Column("SollDrehzahl", Set Each Value(Random Normal())),
New Column("Soll_drehzahl"),
New Column("Ist_drehzahl"),
New Column("Maschinenleistung"),
);
st = HPTime();
for(i=1,i<=NRows(dt),i++,
if(dt:Statusnummer[i] == 1,
if(!isMissing(dt:Drehzahl[i]) & !isMissing(dt:geschw[i]),
ist = dt:Drehzahl[i];
soll = dt:SollDrehzahl[i];
dt:Soll_drehzahl[i] = soll;
dt:Ist_drehzahl[i] = ist;
dt:Maschinenleistung[i] = 100*ist/soll;
);
);
);
t_loop = HPTime() - st;
st = HPTime();
m = dt[0, {"Statusnummer", "Drehzahl", "geschw"}]; // makes a matrix
//check the matrix
v = m[0, 1] // don't need to do a check if it's 0 or 1
&
!ismissing(m[0, 2]) // check if drehzahl is missing
&
!ismissing(m[0, 3]); // check if drehzahl is missing
rows = loc(v); // this is the rows you want to do stuff on now.
//now just set all at once
soll = dt[rows, "Soll_drehzahl"] = dt:SollDrehzahl[rows]; // assign the rows and variable simultaneously
ist = dt[rows, "Ist_drehzahl"] = dt:Drehzahl[rows]; // same thing
dt[rows, "Maschinenleistung"] = 100 * ist :*</img> (1/soll); // do an element wise matrix division
t_mat = HPTime() - st;
st = HPTime();
rows = dt << get rows where(dt:Statusnummer == 1 &
!Is Missing(dt:Drehzahl) &
!Is Missing( dt:geschw ));
//now just set all at once
soll = dt[rows, "Soll_drehzahl"] = dt:SollDrehzahl[rows]; // assign the rows and variable simultaneously
ist = dt[rows, "Ist_drehzahl"] = dt:Drehzahl[rows]; // same thing
dt[rows, "Maschinenleistung"] = 100 * ist :*</img> (1/soll); // do an element wise matrix division
t_get_where = HPTime() - st;
show(t_loop, t_mat, t_get_where);
Quand j'ai effectué cette comparaison, j'ai obtenu
t_loop = 11259288 ;
t_mat = 206942 ;
Mis à jour
t_loop = 11950585;
t_mat = 205366;
t_get_where = 6742823;
Re : Comportement de boucle très lentCela pourrait accélérer les choses - limitez votre boucle aux seules lignes répondant à vos conditions.
found_rows = dt << get rows where(dt:Statusnummer == 1 &
!Is Missing(dt:Drehzahl) &
!Is Missing( dt:geschw ));
for (i = 1, i <= nrows(found_rows), i++,
k = found_rows[i];
dt:Soll_drehzahl[k] = dt:SollDrehzahl[k];
dt:Ist_drehzahl[k] = dt:Drehzahl[k];
dt:Maschinenleistung[k] = 100 * dt:Ist_drehzahl[k] / dt:Soll_drehzahl[k] ;
);Re : Comportement de boucle très lentPeut-être avez-vous un autre rapport ouvert et mis à jour pour chaque modification que vous apportez au tableau. Vous pouvez faire ceci avant et après votre boucle :
dt << Begin Data Update;
// the loop
dt << End Data Update;
Re : Comportement de boucle très lent|Salut Ron, merci. Les boucles imbriquées sont destinées à le rendre plus rapide,
car la première condition échoue sur plusieurs lignes, de sorte que la boucle peut
(et c'est le cas) commencez par le haut en utilisant la ligne suivante. donc de la fonctionnalité
tout fonctionne. Cependant, j'ai revérifié où cela devient lent. Dans le
débogueur, l'accès à la table de données pour réécrire les valeurs a pris du temps :
dt:Soll_drehzahl[i] = soll; dt:Ist_drehzahl[i] = ist;
dt:Maschinenleistung[i] = 100*ist/soll;|
Je les ai donc commentés (//) ==> résultat : très rapide
J'ai effacé les marques de commentaire (//) et..... toujours très vite (!)
.......(Même code, même structure,....)
Cela fonctionne donc maintenant, mais je ne sais toujours pas quelle est la cause du problème. Peut être
quelque chose dans mon système est corrompu.
Merci pour les suggestions.
Re : Comportement de boucle très lentSalut @MWalther
J'essaierais de faire cela comme Jeff l'a suggéré en utilisant des formules de colonnes. n'oubliez pas que vous pouvez toujours supprimer les formules ou simplement supprimer leurs évaluations si vous ne souhaitez pas qu'elles soient constamment réévaluées.
si vous insistez pour utiliser la méthode de la boucle for, je verrais d'abord si les derniers points-virgules sont nécessaires.
de plus, j'essaierais de simplifier l'instruction if imbriquée en une liste plus longue de conditions.
enfin, utiliser le de bugger sur un sous-échantillon et voir ce qui se passe dans la boucle prend plus de temps. J'ai l'impression qu'il y a quelque chose d'involontaire qui prend la plupart du temps.
faites-nous savoir si quelque chose s'améliore.
Re : Comportement de boucle très lentCher Jeff, merci pour la réponse. Formules à cet endroit du script
n'aide pas. (C'est ma section de tri et de nettoyage des données, où je veux
pour éviter les formules)
Je rencontre le même problème à différents endroits. Et quelques formules
ont également été touchés.
Il semble que le processus se fige presque complètement (j'ai compté 1
ligne/seconde !) bien que le CPU continue à charger !
Le résultat est cependant correct une fois terminé.
Bien à vous Martre
Re : Comportement de boucle très lentAvez-vous essayé de créer ces colonnes dans la table de données en utilisant le Éditeur de formule au lieu de boucler avec JSL ? Cela pourrait être plus efficace.