Portál AbcLinuxu, 13. května 2025 17:40
for N in {1..1000}; do A=$(bc -l <<< "scale=9; s(3.14159/$N)") B=$(bc -l <<< "scale=9; c(3.14159/$N)") printf "$A;$B" doneJe to teda dost zjednodušený, aby se v tom dalo vyznat.
Řešení dotazu:
#!/bin/bash # test1.sh for N in {1..5000}; do A=$(bc -l <<< "scale=9; s(3.14159/$N)" &) B=$(bc -l <<< "scale=9; c(3.14159/$N)" &) wait printf "$A;$B\n" donePokud máš více jak 2 jádra, je asi lepší paralelizovat iterace:
#!/bin/bash # test2.sh function wait_for_threads() { while [ $(jobs -rp | wc -l) -ge $threads ]; do sleep $check_interval_secs; done } threads=$(grep processor /proc/cpuinfo | wc -l) check_interval_secs=0.01 for N in {1..5000}; do wait_for_threads ( A=$(bc -l <<< "scale=9; s(3.14159/$N)") B=$(bc -l <<< "scale=9; c(3.14159/$N)") printf "$N $A;$B\n" ) & done | sort -n | cut -d' ' -f2-Režie bude ale obrovská, vzhledem k rychlosti k výpočtu v bc. Takže by to chtělo rozdělit iterace do clusterů, které by byli prováděny paralelně:
#!/bin/bash # test3.sh iters=5000 threads=$(grep processor /proc/cpuinfo | wc -l) cluster_size=$((iters/threads)) last_cluster_size=$((iters-cluster_size*(threads-1))) temp=$(mktemp -d) for C in $(seq $threads); do first_iter=$(( (C-1) * cluster_size + 1 )) if [ $C -lt $threads ]; then last_iter=$(( first_iter + cluster_size -1 )) else last_iter=$(( first_iter + last_cluster_size -1 )) fi ( for N in $(seq $first_iter $last_iter); do A=$(bc -l <<< "scale=9; s(3.14159/$N)") B=$(bc -l <<< "scale=9; c(3.14159/$N)") printf "$A;$B\n" done ) > $temp/$C.list & done wait for C in $(seq $threads); do cat $temp/$C.list rm $temp/$C.list done rmdir $tempBenchmark na i5 (4 core):
$ time ./test0.sh > test0.output # original bez paralelizace real 0m15.776s user 0m0.928s sys 0m1.628s $ time ./test1.sh > test1.output real 0m12.012s user 0m0.608s sys 0m1.588s $ time ./test2.sh > test2.output real 0m11.803s user 0m1.300s sys 0m1.288s $ time ./test3.sh > test3.output real 0m3.278s user 0m0.388s sys 0m0.808s $ for i in 1 2 3; do cmp test0.output test$i.output; echo $?; done 0 0 0
CPU=$(grep processor /proc/cpuinfo | wc -l) for S in $(seq 1 $CPU); do sleep .00$((S-1)) for N in $(seq $S $CPU 1000); do A=$(bc -l <<< "scale=9; s(3.14159/$N)") B=$(bc -l <<< "scale=9; c(3.14159/$N)") printf "$A;$B" done & done wait
/bin/dash
, který by měl být upraven pro dávkové zpracování.
/bin/dash
hodně zjednodušený, aby běhal co nejrychleji a dělal jen to nezbytné, co shell musí umět. Pro daný případ se tedy nehodí.
bc
, Pythonu, Perlu, AWK, Haskellu nebo čemkoli jiném, co je výkonnější než Bash? Přeskakovat při každém průchodu cyklem do bc a zpátky není vůbec efektivní. Navíc se Bash na zpracování čísel vůbec nehodí.
#!/bin/bash bc -l <<EOT scale = 9 for (n = 1; n <= 1000; n++) { print s(3.14159/n), ";", c(3.14159/n), "\n"; } quit EOT
#!/bin/bash bc_call() { bc -l <<EOT scale = 9 for (n = 1; n <= 1000; n++) { print s(3.14159/n), " ", c(3.14159/n), "\n"; } EOT } bc_call | while read A B; do printf "\e[${B};${A}H\e[48;5;161m \e[0m" done
Tiskni
Sdílej:
ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.