Précédent   Forum des professionnels en informatique > Systèmes > Linux > Applications > Shell
Shell Vos questions sur l'utilisation des commandes shell
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 06/05/2011, 11h44   #1
Invité régulier
 
Inscription : janvier 2009
Messages : 12
Détails du profil
Informations forums :
Inscription : janvier 2009
Messages : 12
Points : 5
Points : 5
Par défaut demande de conseil pour optimiser mon script

bonjour,

voilà, je suis débutant en bash. ceci est en fait mon 1er script. ça m'a pris quelques jours pour en arriver là (et quelques posts sur le forum).
le résultat fait exactement ce que je veux mais est incroyablement lent. mon pc n'est pas une bête de compét, mais à la vitesse où ça avance, il y en a pour plusieurs jours de calcul....
je me dis que je n'ai pas forcément choisi les solutions les plus rapides de calcul. mais pour l'instant, je n'en connais pas d'autres...
alors, ce serait sympa si quelqu'un pouvait me donner quelques pistes pour optimiser mon script
ce script fait des profils swath (sur une bande de 10km de large, on calcule l'altitude moyenne, les valeurs min et max; et ceci pour chaque point du profil (environ une valeur tous les 90mètres, sur un profil d'environ 350km de long)


Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# definition du nom de sortie à partir des coordonnées de la coupe
separe1_name=$(echo $start_proj | awk -F "/" '{print $1}')
separe2_name=$(echo $start_proj | awk -F "/" '{print $2}')
separe3_name=$(echo $end_proj | awk -F "/" '{print $1}')
separe4_name=$(echo $end_proj | awk -F "/" '{print $2}')
name_output=$separe1_name"-"$separe2_name"-"$separe3_name"-"$separe4_name
 
>mean_$name_output.txt
>min_$name_output.txt
>max_$name_output.txt
 
mean_y=0
min_y=10000
max_y=0
compteur=0
 
while read pos val
do
 
x=$(printf "%.2f\n" $pos)       #on arrondit pos à 2 chiffres après la virgule
 
y=$(printf "%.2f\n" $val)       #on arrondit val à 2 chiffres après la virgule 
 
if [ $(echo "$y < 0.00" | bc) -eq 1 ]; then    #on élimine z négatif et NaN
y=0                                    #si le test est vrai (y<0),il renvoie 1 
fi                                             #on remplace y par 0

# du à l'effet combiné de l'arrondi des valeurs (par printf) issues de gmt_project, des valeurs correspondant à la même ligne de SRTM sont quelquefois espacées de 0.01. on fait donc un test: si seulement l'écart est supérieur à 0.01, on considère qu'on est passé à une nouvelle ligne de données)

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
diff=$(echo "$x-$i" | bc)
 
    if [ $(echo "$diff <= 0.01" | bc) -eq 1 ]
        then mean_y=$(echo "$mean_y+$y" | bc)
        ((compteur = $compteur + 1))
        if [ $(echo "$y < $min_y" | bc) -eq 1 ]; then
        min_y=$y
        fi
        if [ $(echo "$y > $max_y" | bc) -eq 1 ]; then
        max_y=$y
        fi
    else
        mean_y=$(echo "$mean_y/$compteur" | bc)
        echo $i $mean_y >> mean_$name_output.txt
echo position:$i moyenne:$mean_y min:$min_y max:$max_y compteur:$compteur
        echo $i $min_y >> min_$name_output.txt
        echo $i $max_y >> max_$name_output.txt
 
                i=$x                        # on change la valeur de i
        mean_y=$y
        max_y=$y
        min_y=$y
        compteur=1
    fi
 
done < $fich

merci d'avance,
seb
seb.garcia est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 06/05/2011, 13h27   #2
Expert Confirmé Sénior
 
Avatar de N_BaH
 
Inscription : février 2008
Messages : 2 070
Détails du profil
Informations forums :
Inscription : février 2008
Messages : 2 070
Points : 4 153
Points : 4 153
Bonjour,

tu devrais tout passer sous awk.
N_BaH est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 09/05/2011, 13h43   #3
Membre Expert
 
Homme Alexis
Intégrateur d'Exploitation
Inscription : février 2003
Messages : 876
Détails du profil
Informations personnelles :
Nom : Homme Alexis
Âge : 32
Localisation : France

Informations professionnelles :
Activité : Intégrateur d'Exploitation
Secteur : Biens de consommation

Informations forums :
Inscription : février 2003
Messages : 876
Points : 1 619
Points : 1 619
Envoyer un message via ICQ à Alek-C Envoyer un message via Skype™ à Alek-C
Tu n'es pas obligé d'utiliser bc pour toutes tes opérations : bash permet de faire des comparaisons et des calculs simples

Sinon, le script me paraît affreusement compliqué pour un problème à première vue assez simple : j'ai cru comprendre que tu avais un fichier en entrée qui comporte 2 valeurs par ligne (x et y) mais le coup des arrondis et la gestion des positions m'échappent un peu par rapport à ton traitement, donc si tu pouvais donner le format et un exemple de ton fichier en entrée, ça pourrait aider à te proposer mieux.

Sinon, effectivement, utiliser awk ou perl pour tout faire semble une bonne approche (mais pas forcément indispensable à mon avis).
Alek-C est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 11/05/2011, 15h54   #4
Invité régulier
 
Inscription : janvier 2009
Messages : 12
Détails du profil
Informations forums :
Inscription : janvier 2009
Messages : 12
Points : 5
Points : 5
bonjour,

réponse avec un peu de retard (en fait, je viens juste de finir de le réécrire en awk comme suggéré par N BaH). ca tourne impec et rapidement. merci

Il s'agit de mon 1er script awk. peut sûrement mieux faire....

Alek-C:
Comme tu peux voir, je ne passe plus par le calcul des arrondis (ca prend énormément de temps de calcul)

Je lance ce script depuis un script bash (j'en ai besoin pour faire tourner des trucs qui ne marchent pas sous awk)

partie du script bash:
Code :
1
2
n=$(wc -l strip_sampling_$name_output.pz | gawk '{print $1}')
gawk -f E:/GMTscripts-grd/PARAM/swath.gawk n=$n < strip_sampling_$name_output.pz
script awk:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#!/bin/gawk -f
 
 
BEGIN {
i = 0
sum_y = 0
min_y = 10000
max_y = 0
compteur = 0
}
 
{
for (k=1 ; k<=n ; k++)
{
getline 
 
#toutes les altitudes inférieures à 0 sont corrigées
	if ($2 < 0)
	{
	$2=0
	}
 
diff=$1-i
	if (diff <= 0.02)
		{
		sum_y=sum_y+$2
		compteur=compteur+1
		if ($2 < min_y) min_y = $2 
		if ($2 > max_y) max_y = $2
		}
	else
		{
		mean_y=sum_y/compteur
print "position:"i, "sum:"sum_y, "moyenne:"mean_y, "min:"min_y, "max:"max_y, "compteur:"compteur
		print i, mean_y >> "mean.txt"
                print i, min_y >> "min.txt"
		print i, max_y >> "max.txt"
		i=$1
		sum_y=$2
		max_y=$2
		min_y=$2
		compteur=1
		}	
 
}
}
Mon fichier d'entrée résulte de la projection (par l'outil project de GMT www.soest.hawaii.edu/gmt/) de tous les points (longitude, latitude, altitude) situés à 5km de part et d'autre d'un trait de coupe. J'ai donc un fichier (p,z), p étant le projeté de (longitude,latitude) sur mon trait de coupe, exprimé en distance kilométrique depuis le début du trait de coupe. Mon trait de coupe pouvant être oblique, je ne peux pas me contenter de la latitude ou de la longitude des points. Tout le problème vient que le résultat de project donne des valeurs de p différentes pour, par exemple, des points situés à la même latitude le long d'un profil Nord-Sud (voir exemple ci-dessous). Les écarts sont très faibles mais m'empêche de calculer directement la moyenne et de déterminer les valeurs min et max pour toutes les données perpendiculaires en chaque point au profil (à la même latitude dans le cas d'un profil N-S). L'astuce que j'ai trouvé, sachant que j'ai un point tous les 90mètres dans ma base de données topographiques (SRTM de la NASA) est de comparer la distance entre 2 points successifs (nommé diff dans le script awk). Si elle est inférieure à un certain seuil (ici 0.02), alors ces points sont sur la même latitude.

Voici un exemple de fichier d'entrée (p,z). p est en kilomètre, z est en mètre.

0.00184575568891 0.00028742471477
0.00184575568891 376.046569824
0.00189395585363 395.98916626
0.00189395585363 4.1547946239e-007
0.00194791213731 414.259521484
0.00194791213731 0.000286347582005
0.0926625226018 0.00034032255644
0.0926628630255 0.000665176485199
0.0926628630255 0.000674647395499
0.092663884289 0.000669857836328
0.092663884289 0.000651132315397
0.0926655377394 0.000326278415741


seb
ps: pour ceux qui se demandent à quoi tout ca sert, je suis géologue. c'est pour faire des profils topo dans les alpes
seb.garcia est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 11/05/2011, 16h03   #5
Membre Expert
 
Homme Alexis
Intégrateur d'Exploitation
Inscription : février 2003
Messages : 876
Détails du profil
Informations personnelles :
Nom : Homme Alexis
Âge : 32
Localisation : France

Informations professionnelles :
Activité : Intégrateur d'Exploitation
Secteur : Biens de consommation

Informations forums :
Inscription : février 2003
Messages : 876
Points : 1 619
Points : 1 619
Envoyer un message via ICQ à Alek-C Envoyer un message via Skype™ à Alek-C
Beau travail

Ajoute juste des balises CODE autour de ton programme et ça sera parfait

Et clique sur résolu pendant que tu y es :p
Alek-C est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 09h07.


 
 
 
 
Partenaires

Hébergement Web