중첩된 while 루프 반복을 위한 GNU 병렬

중첩된 while 루프 반복을 위한 GNU 병렬

슈퍼컴퓨터에서 30시간이 걸리는 코드가 있는데 관리자는 한 번에 하나의 코어만 사용할 수 있다고 말합니다. 60 x 60 매트릭스를 통해 이미징 코드를 실행하고 zdichi_eps 이미징 프로그램을 실행하고 매 반복(3600회)마다 파일에 데이터를 씁니다. 제 생각에는 GNU PARALLEL 명령을 사용하고 두 개의 while 루프 대신 for 루프를 사용하여 아래 스크립트를 다시 작성할 수 있다는 것입니다. 최대 64코어까지 사용할 수 있으니 시간이 많이 단축될 것 같아요. 한번 보시고 어떻게 생각하는지 말씀해 주세요. 어떻게 바뀔까요? 가능합니까? 감사해요! 데이터 센터와의 싸움에서 나를 구해 줄 작업 버전을 얻는 데 도움을 줄 수 있는 모든 사람에게 기꺼이 기부하겠습니다!

set tb = gau_9.tab      # tab file
set target = reformat   # target name (from the command line)
set dte = May2010v1     # date of the run.
set mult1 = 0.7958  # multiplication factor
set mult2 = `echo $mult1 | awk '{printf("%.6f",$1/2)}'`
set inclin = 40       # inclination angle
set vsin = 113.3        # vsini
set aim = 0.03221 # <chisq aim>
set tphot = 5600    # photosphere temperature
set tspot = 4100    # spot temperature
set omega0 = 11.0038    # omega_0; matched to the period
set startx = 10.8   # starting omega_eq
set stepx = 0.01    # step in omega_eq
set nx = 60         # number of datapoint for omega_eq
set starty = 0.0     # starting domega
set stepy = 0.01    # step in domega
set ny = 60     # number of datapoints for domega.
set npts = 30       # number of points used in zdichi_ep        set spec = 
$target.rs
set tab  = $tb
set b1 = $target.b1
set s1 = $target.s1
set out  = $target$aim$dte.out
set map  = $target$aim$dte.m
set junk = $target.dr_junk
set screen = $target.screen.dat
set zdi = $target.zdi.in
set om
set do

set ntot = 0
echo " " > $out 
echo " " > $junk
echo " " > $screen

echo "starting diffrot" > $target.afile

set i = 0 

while ($i < $nx) 
  set omega = `echo $startx $stepx $i | awk '{printf("%.5f",$1+$2*$3)}'`
  echo "Count i, Count ny " $i $ny
  echo "omega : " $omega
  set line
  set j = 0 
  while ($j < $ny) 
    echo "Count J Count ny " $j  $ny
    set domeg = `echo $starty $stepy $j | awk '{printf("%.5f",$1+$2*$3)}'`
    echo "1 delta omega : " $domeg
    set test = `echo $omega $domeg | awk '{tmp = $1-0.361387*$2-4.461019; 
    tmp = sqrt(tmp*tmp); if (tmp < 0.02) print 1; else print 0; }'`
    echo "test value : " $test 
    set test = 1
    if ($test == 0) then
        set spot = 9.000000
        set chi2 = 9.000000
        set testzdi = 9.00000
    else
        set beta  = `echo $omega $omega0 | awk '{printf("%e",1.0-$1/$2)}'`
        set gamma = `echo $domeg $omega0 | awk '{printf("%e",$1/$2)}'`
        echo "test, beta and gamma : " $test $beta $gamma
        echo "22 sending data to zdichi via diffrot2"
        echo "33 The data sent :" $vsin $spec $tab $mult1 $beta $aim $gamma $mult2 >> $screen

        # setting up the input file for zdichi_eps

        echo n > $zdi
        echo n >> $zdi
        echo 5000 $inclin $vsin >> $zdi
        echo n >> $zdi
        echo 1 >> $zdi
        echo $tphot $tspot >> $zdi
        echo $beta $gamma >> $zdi
        echo $spec >> $zdi
        echo $tab >> $zdi
        echo $mult1 $mult2 >> $zdi
        echo y >> $zdi
        echo 1.0 >> $zdi
        echo 1 >> $zdi
        echo y >> $zdi
        echo 1 >> $zdi
        echo $aim $npts >> $zdi
        echo $b1 >> $zdi
        echo y >> $zdi
        echo $s1 >> $zdi

        # finished setting up the input file for zdichi_eps

        /home/zdichi_eps < $zdi >> $out
        echo "44 finished with zdichi" 
        @ ntot++ 
        set chi2 = `tail -20 $out | grep '<29>' | awk '{printf("%.6f", $3)}'`
        set spot = `tail -20 $out | grep '<29>' | awk '{printf("%.6f", $5)}'`
        set testzdi = `tail -20 $out | grep '<29>' | awk '{printf("%.6f", $6)}'`
        echo "55 The returned values were: " $omega $domeg $test $chi2 $spot $testzdi >> $screen
    endif   

    if ($i == 0) then 
        set do = `echo $do $domeg`
    endif

    set line = `echo $line $chi2`
    @ j++

  end
  set om = `echo $om $omega`
  echo $line >> $junk
  @ i++
end

답변1

다음과 같은 것을 병렬화하는 가장 빠른 방법은 다음과 같습니다.

  1. 모든 매개변수 파일 쓰기reformat.zdi.${i}_${j}.in
  2. 각 파일에 대해 프로그램을 병렬로 호출하여

예를 들면 다음과 같습니다.

#!/bin/bash
for f in ./reformat.zdi.*.in ;do
    echo "/home/zdichi_eps < $f > ${f%.in}.out"
done | parallel -j64

답변2

$iBash에서 선호되는 접근 방식은 및 인수를 받아들이는 함수를 만드는 것입니다 $j.

do_zdichi() {
  i="$1"
  j="$2"
  [set all variables here]
  /home/zdichi_eps < $zdi >> $out
  [postprocess output]
}
export -f do_zdichi
eval parallel do_zdichi ::: {0..$nx} ::: {0..$ny}

output.$i.$j함수에서 작성하는 모든 파일 이름이 고유한 이름( 가능하지만 그렇지 않음) 을 갖고 있는지 확인하면 myoutput병렬로 실행되는 다른 프로세스에서 해당 파일을 덮어쓰지 않습니다.

관련 정보