1*906afcb8SAndy Fiddaman#!/usr/bin/ksh93 2*906afcb8SAndy Fiddaman 3*906afcb8SAndy Fiddaman# 4*906afcb8SAndy Fiddaman# CDDL HEADER START 5*906afcb8SAndy Fiddaman# 6*906afcb8SAndy Fiddaman# The contents of this file are subject to the terms of the 7*906afcb8SAndy Fiddaman# Common Development and Distribution License (the "License"). 8*906afcb8SAndy Fiddaman# You may not use this file except in compliance with the License. 9*906afcb8SAndy Fiddaman# 10*906afcb8SAndy Fiddaman# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 11*906afcb8SAndy Fiddaman# or http://www.opensolaris.org/os/licensing. 12*906afcb8SAndy Fiddaman# See the License for the specific language governing permissions 13*906afcb8SAndy Fiddaman# and limitations under the License. 14*906afcb8SAndy Fiddaman# 15*906afcb8SAndy Fiddaman# When distributing Covered Code, include this CDDL HEADER in each 16*906afcb8SAndy Fiddaman# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 17*906afcb8SAndy Fiddaman# If applicable, add the following below this CDDL HEADER, with the 18*906afcb8SAndy Fiddaman# fields enclosed by brackets "[]" replaced with your own identifying 19*906afcb8SAndy Fiddaman# information: Portions Copyright [yyyy] [name of copyright owner] 20*906afcb8SAndy Fiddaman# 21*906afcb8SAndy Fiddaman# CDDL HEADER END 22*906afcb8SAndy Fiddaman# 23*906afcb8SAndy Fiddaman 24*906afcb8SAndy Fiddaman# 25*906afcb8SAndy Fiddaman# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. 26*906afcb8SAndy Fiddaman# 27*906afcb8SAndy Fiddaman 28*906afcb8SAndy Fiddaman# 29*906afcb8SAndy Fiddaman# mandelbrotset1 - a simple mandelbrot set generation and 30*906afcb8SAndy Fiddaman# parallel execution demo 31*906afcb8SAndy Fiddaman# 32*906afcb8SAndy Fiddaman 33*906afcb8SAndy Fiddaman# Solaris needs /usr/xpg6/bin:/usr/xpg4/bin because the tools in /usr/bin are not POSIX-conformant 34*906afcb8SAndy Fiddamanexport PATH=/usr/xpg6/bin:/usr/xpg4/bin:/bin:/usr/bin 35*906afcb8SAndy Fiddaman 36*906afcb8SAndy Fiddaman# Make sure all math stuff runs in the "C" locale to avoid problems 37*906afcb8SAndy Fiddaman# with alternative # radix point representations (e.g. ',' instead of 38*906afcb8SAndy Fiddaman# '.' in de_DE.*-locales). This needs to be set _before_ any 39*906afcb8SAndy Fiddaman# floating-point constants are defined in this script). 40*906afcb8SAndy Fiddamanif [[ "${LC_ALL}" != "" ]] ; then 41*906afcb8SAndy Fiddaman export \ 42*906afcb8SAndy Fiddaman LC_MONETARY="${LC_ALL}" \ 43*906afcb8SAndy Fiddaman LC_MESSAGES="${LC_ALL}" \ 44*906afcb8SAndy Fiddaman LC_COLLATE="${LC_ALL}" \ 45*906afcb8SAndy Fiddaman LC_CTYPE="${LC_ALL}" 46*906afcb8SAndy Fiddaman unset LC_ALL 47*906afcb8SAndy Fiddamanfi 48*906afcb8SAndy Fiddamanexport LC_NUMERIC=C 49*906afcb8SAndy Fiddaman 50*906afcb8SAndy Fiddamanfunction printmsg 51*906afcb8SAndy Fiddaman{ 52*906afcb8SAndy Fiddaman print -u2 "$*" 53*906afcb8SAndy Fiddaman} 54*906afcb8SAndy Fiddaman 55*906afcb8SAndy Fiddamanfunction fatal_error 56*906afcb8SAndy Fiddaman{ 57*906afcb8SAndy Fiddaman print -u2 "${progname}: $*" 58*906afcb8SAndy Fiddaman exit 1 59*906afcb8SAndy Fiddaman} 60*906afcb8SAndy Fiddaman 61*906afcb8SAndy Fiddaman# Get terminal size and put values into a compound variable with the integer 62*906afcb8SAndy Fiddaman# members "columns" and "lines" 63*906afcb8SAndy Fiddamanfunction get_term_size 64*906afcb8SAndy Fiddaman{ 65*906afcb8SAndy Fiddaman nameref rect=$1 66*906afcb8SAndy Fiddaman 67*906afcb8SAndy Fiddaman rect.columns=${ tput cols ; } || return 1 68*906afcb8SAndy Fiddaman rect.lines=${ tput lines ; } || return 1 69*906afcb8SAndy Fiddaman 70*906afcb8SAndy Fiddaman return 0 71*906afcb8SAndy Fiddaman} 72*906afcb8SAndy Fiddaman 73*906afcb8SAndy Fiddamanfunction mandelbrot 74*906afcb8SAndy Fiddaman{ 75*906afcb8SAndy Fiddaman nameref result=$1 76*906afcb8SAndy Fiddaman float x=$2 77*906afcb8SAndy Fiddaman float y=$3 78*906afcb8SAndy Fiddaman float xx 79*906afcb8SAndy Fiddaman float yy 80*906afcb8SAndy Fiddaman float x1=$4 81*906afcb8SAndy Fiddaman float y1=$5 82*906afcb8SAndy Fiddaman integer iteration=$6 83*906afcb8SAndy Fiddaman integer max_iteration=$7 84*906afcb8SAndy Fiddaman float mag 85*906afcb8SAndy Fiddaman 86*906afcb8SAndy Fiddaman for (( mag=0 ; mag < max_mag && iteration < max_iteration ; iteration++ )) ; do 87*906afcb8SAndy Fiddaman (( 88*906afcb8SAndy Fiddaman xx=x*x , 89*906afcb8SAndy Fiddaman yy=y*y , 90*906afcb8SAndy Fiddaman mag=xx+yy , 91*906afcb8SAndy Fiddaman y=x*y*2+y1 , 92*906afcb8SAndy Fiddaman x=xx-yy+x1 93*906afcb8SAndy Fiddaman )) 94*906afcb8SAndy Fiddaman done 95*906afcb8SAndy Fiddaman 96*906afcb8SAndy Fiddaman (( result=iteration )) 97*906afcb8SAndy Fiddaman 98*906afcb8SAndy Fiddaman return 0 99*906afcb8SAndy Fiddaman} 100*906afcb8SAndy Fiddaman 101*906afcb8SAndy Fiddaman# build mandelbrot image serially 102*906afcb8SAndy Fiddamanfunction loop_serial 103*906afcb8SAndy Fiddaman{ 104*906afcb8SAndy Fiddaman integer value 105*906afcb8SAndy Fiddaman typeset line="" 106*906afcb8SAndy Fiddaman 107*906afcb8SAndy Fiddaman for (( y=y_min ; y < y_max ; y+=stepwidth )) ; do 108*906afcb8SAndy Fiddaman for (( x=x_min ; x < x_max ; x+=stepwidth )) ; do 109*906afcb8SAndy Fiddaman mandelbrot value ${x} ${y} ${x} ${y} 1 ${symbollistlen} 110*906afcb8SAndy Fiddaman line+="${symbollist:value:1}" 111*906afcb8SAndy Fiddaman done 112*906afcb8SAndy Fiddaman 113*906afcb8SAndy Fiddaman line+=$'\n' 114*906afcb8SAndy Fiddaman done 115*906afcb8SAndy Fiddaman 116*906afcb8SAndy Fiddaman print -r -- "${line}" 117*906afcb8SAndy Fiddaman 118*906afcb8SAndy Fiddaman return 0 119*906afcb8SAndy Fiddaman} 120*906afcb8SAndy Fiddaman 121*906afcb8SAndy Fiddaman# build mandelbrot image using parallel worker jobs 122*906afcb8SAndy Fiddamanfunction loop_parallel 123*906afcb8SAndy Fiddaman{ 124*906afcb8SAndy Fiddaman integer numjobs=0 125*906afcb8SAndy Fiddaman # the following calculation suffers from rounding errors 126*906afcb8SAndy Fiddaman integer lines_per_job=$(( ((m_height+(numcpus-1)) / numcpus) )) 127*906afcb8SAndy Fiddaman typeset tmpjobdir 128*906afcb8SAndy Fiddaman 129*906afcb8SAndy Fiddaman printmsg $"# lines_per_job=${lines_per_job}" 130*906afcb8SAndy Fiddaman printmsg $"# numcpus=${numcpus}" 131*906afcb8SAndy Fiddaman 132*906afcb8SAndy Fiddaman # "renice" worker jobs 133*906afcb8SAndy Fiddaman set -o bgnice 134*906afcb8SAndy Fiddaman 135*906afcb8SAndy Fiddaman tmpjobdir="$(mktemp --default=/tmp --directory "mandelbrotset1${PPID}_$$_XXXXXX")" || fatal_error $"Could not create temporary directory." 136*906afcb8SAndy Fiddaman trap "rm -r ${tmpjobdir}" EXIT # cleanup 137*906afcb8SAndy Fiddaman 138*906afcb8SAndy Fiddaman # try to generate a job identifer prefix which is unique across multiple hosts 139*906afcb8SAndy Fiddaman jobident="job_host_$(uname -n)pid_$$_ppid${PPID}" 140*906afcb8SAndy Fiddaman 141*906afcb8SAndy Fiddaman printmsg $"## prepare..." 142*906afcb8SAndy Fiddaman for (( y=y_min ; y < y_max ; y+=(stepwidth*lines_per_job) )) ; do 143*906afcb8SAndy Fiddaman rm -f "${tmpjobdir}/${jobident}_child_$y.joboutput" 144*906afcb8SAndy Fiddaman 145*906afcb8SAndy Fiddaman (( numjobs++ )) 146*906afcb8SAndy Fiddaman done 147*906afcb8SAndy Fiddaman 148*906afcb8SAndy Fiddaman printmsg $"## running ${numjobs} children..." 149*906afcb8SAndy Fiddaman for (( y=y_min ; y < y_max ; y+=(stepwidth*lines_per_job) )) ; do 150*906afcb8SAndy Fiddaman ( 151*906afcb8SAndy Fiddaman integer value 152*906afcb8SAndy Fiddaman typeset line="" 153*906afcb8SAndy Fiddaman # save file name since we're going to modify "y" 154*906afcb8SAndy Fiddaman typeset filename="${tmpjobdir}/${jobident}_child_$y.joboutput" 155*906afcb8SAndy Fiddaman 156*906afcb8SAndy Fiddaman for (( ; y < y_max && lines_per_job-- > 0 ; y+=stepwidth )) ; do 157*906afcb8SAndy Fiddaman for (( x=x_min ; x < x_max ; x+=stepwidth )) ; do 158*906afcb8SAndy Fiddaman mandelbrot value ${x} ${y} ${x} ${y} 1 ${symbollistlen} 159*906afcb8SAndy Fiddaman line+="${symbollist:value:1}" 160*906afcb8SAndy Fiddaman done 161*906afcb8SAndy Fiddaman 162*906afcb8SAndy Fiddaman line+=$'\n' 163*906afcb8SAndy Fiddaman done 164*906afcb8SAndy Fiddaman print -r -- "${line}" >"${filename}" 165*906afcb8SAndy Fiddaman 166*906afcb8SAndy Fiddaman exit 0 167*906afcb8SAndy Fiddaman ) & 168*906afcb8SAndy Fiddaman done 169*906afcb8SAndy Fiddaman 170*906afcb8SAndy Fiddaman printmsg $"## waiting for ${numjobs} children..." 171*906afcb8SAndy Fiddaman wait 172*906afcb8SAndy Fiddaman 173*906afcb8SAndy Fiddaman printmsg $"## output:" 174*906afcb8SAndy Fiddaman for (( y=y_min ; y < y_max ; y+=(stepwidth*lines_per_job) )) ; do 175*906afcb8SAndy Fiddaman print -r -- "$( < "${tmpjobdir}/${jobident}_child_$y.joboutput")" 176*906afcb8SAndy Fiddaman # EXIT trap will cleanup temporary files 177*906afcb8SAndy Fiddaman done 178*906afcb8SAndy Fiddaman 179*906afcb8SAndy Fiddaman return 0 180*906afcb8SAndy Fiddaman} 181*906afcb8SAndy Fiddaman 182*906afcb8SAndy Fiddamanfunction usage 183*906afcb8SAndy Fiddaman{ 184*906afcb8SAndy Fiddaman OPTIND=0 185*906afcb8SAndy Fiddaman getopts -a "${progname}" "${mandelbrotset1_usage}" OPT '-?' 186*906afcb8SAndy Fiddaman exit 2 187*906afcb8SAndy Fiddaman} 188*906afcb8SAndy Fiddaman 189*906afcb8SAndy Fiddaman# main 190*906afcb8SAndy Fiddamanbuiltin basename 191*906afcb8SAndy Fiddamanbuiltin cat 192*906afcb8SAndy Fiddamanbuiltin rm 193*906afcb8SAndy Fiddamanbuiltin uname # loop_parallel needs the ksh93 builtin version to generate unique job file names 194*906afcb8SAndy Fiddamanbuiltin mktemp 195*906afcb8SAndy Fiddaman 196*906afcb8SAndy Fiddamanset -o noglob 197*906afcb8SAndy Fiddamanset -o nounset 198*906afcb8SAndy Fiddaman 199*906afcb8SAndy Fiddamantypeset progname="${ basename "${0}" ; }" 200*906afcb8SAndy Fiddaman 201*906afcb8SAndy Fiddamanfloat x_max 202*906afcb8SAndy Fiddamanfloat x_min 203*906afcb8SAndy Fiddamanfloat y_max 204*906afcb8SAndy Fiddamanfloat y_min 205*906afcb8SAndy Fiddamanfloat m_width 206*906afcb8SAndy Fiddamanfloat m_height 207*906afcb8SAndy Fiddamanfloat max_mag 208*906afcb8SAndy Fiddamanfloat stepwidth 209*906afcb8SAndy Fiddamaninteger numcpus 210*906afcb8SAndy Fiddaman 211*906afcb8SAndy Fiddaman# terminal size rect 212*906afcb8SAndy Fiddamancompound termsize=( 213*906afcb8SAndy Fiddaman integer columns=-1 214*906afcb8SAndy Fiddaman integer lines=-1 215*906afcb8SAndy Fiddaman) 216*906afcb8SAndy Fiddaman 217*906afcb8SAndy Fiddamanget_term_size termsize || fatal_error $"Could not get terminal size." 218*906afcb8SAndy Fiddaman 219*906afcb8SAndy Fiddamantypeset symbollist=' .:0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ%#' 220*906afcb8SAndy Fiddamantypeset symbollistlen=$(( ${#symbollist} - 1)) 221*906afcb8SAndy Fiddamantypeset mode="parallel" 222*906afcb8SAndy Fiddaman 223*906afcb8SAndy Fiddaman(( max_mag=400 )) 224*906afcb8SAndy Fiddaman(( stepwidth=0.1 )) 225*906afcb8SAndy Fiddaman 226*906afcb8SAndy Fiddaman# calculate number of worker CPUs and use 3 as fallback 227*906afcb8SAndy Fiddaman(( numcpus=$(getconf NPROCESSORS_ONLN || print "3") )) 228*906afcb8SAndy Fiddaman(( numcpus=numcpus*4 )) 229*906afcb8SAndy Fiddaman 230*906afcb8SAndy Fiddaman(( m_width=termsize.columns-1 , m_height=termsize.lines-2 )) 231*906afcb8SAndy Fiddaman 232*906afcb8SAndy Fiddamantypeset -r mandelbrotset1_usage=$'+ 233*906afcb8SAndy Fiddaman[-?\n@(#)\$Id: mandelbrotset1 (Roland Mainz) 2010-03-31 \$\n] 234*906afcb8SAndy Fiddaman[-author?Roland Mainz <roland.mainz@nrubsig.org>] 235*906afcb8SAndy Fiddaman[+NAME?mandelbrotset1 - generate mandelbrot set fractals with ksh93] 236*906afcb8SAndy Fiddaman[+DESCRIPTION?\bmandelbrotset1\b mandelbrot set fractal generator 237*906afcb8SAndy Fiddaman which runs either in serial or parallel mode (using multiple worker jobs).] 238*906afcb8SAndy Fiddaman[w:width?Width of fractal.]:[width] 239*906afcb8SAndy Fiddaman[h:height?Height of fractal.]:[height] 240*906afcb8SAndy Fiddaman[s:symbols?Symbols to build the fractal from.]:[symbolstring] 241*906afcb8SAndy Fiddaman[m:mag?Magnification level.]:[magnificationlevel] 242*906afcb8SAndy Fiddaman[p:stepwidth?Width per step.]:[widthperstep] 243*906afcb8SAndy Fiddaman[S:serial?Run in serial mode.] 244*906afcb8SAndy Fiddaman[P:parallel?Run in parallel mode.] 245*906afcb8SAndy Fiddaman[M:mode?Execution mode.]:[mode] 246*906afcb8SAndy Fiddaman[C:numcpus?Number of processors used for parallel execution.]:[numcpus] 247*906afcb8SAndy Fiddaman[+SEE ALSO?\bjuliaset1\b(1), \bksh93\b(1)] 248*906afcb8SAndy Fiddaman' 249*906afcb8SAndy Fiddaman 250*906afcb8SAndy Fiddamanwhile getopts -a "${progname}" "${mandelbrotset1_usage}" OPT ; do 251*906afcb8SAndy Fiddaman# printmsg "## OPT=|${OPT}|, OPTARG=|${OPTARG}|" 252*906afcb8SAndy Fiddaman case ${OPT} in 253*906afcb8SAndy Fiddaman w) m_width="${OPTARG}" ;; 254*906afcb8SAndy Fiddaman h) m_height="${OPTARG}" ;; 255*906afcb8SAndy Fiddaman s) symbollist="${OPTARG}" ;; 256*906afcb8SAndy Fiddaman m) max_mag="${OPTARG}" ;; 257*906afcb8SAndy Fiddaman p) stepwidth="${OPTARG}" ;; 258*906afcb8SAndy Fiddaman S) mode="serial" ;; 259*906afcb8SAndy Fiddaman +S) mode="parallel" ;; 260*906afcb8SAndy Fiddaman P) mode="parallel" ;; 261*906afcb8SAndy Fiddaman +P) mode="serial" ;; 262*906afcb8SAndy Fiddaman M) mode="${OPTARG}" ;; 263*906afcb8SAndy Fiddaman C) numcpus="${OPTARG}" ;; 264*906afcb8SAndy Fiddaman *) usage ;; 265*906afcb8SAndy Fiddaman esac 266*906afcb8SAndy Fiddamandone 267*906afcb8SAndy Fiddamanshift $((OPTIND-1)) 268*906afcb8SAndy Fiddaman 269*906afcb8SAndy Fiddamanprintmsg "# width=${m_width}" 270*906afcb8SAndy Fiddamanprintmsg "# height=${m_height}" 271*906afcb8SAndy Fiddamanprintmsg "# max_mag=${max_mag}" 272*906afcb8SAndy Fiddamanprintmsg "# stepwidth=${stepwidth}" 273*906afcb8SAndy Fiddamanprintmsg "# symbollist='${symbollist}'" 274*906afcb8SAndy Fiddamanprintmsg "# mode=${mode}" 275*906afcb8SAndy Fiddaman 276*906afcb8SAndy Fiddaman(( symbollistlen=${#symbollist}-1 )) 277*906afcb8SAndy Fiddaman 278*906afcb8SAndy Fiddaman(( 279*906afcb8SAndy Fiddaman x_max=m_width*stepwidth/2. , 280*906afcb8SAndy Fiddaman x_min=-x_max , 281*906afcb8SAndy Fiddaman y_max=m_height*stepwidth/2. , 282*906afcb8SAndy Fiddaman y_min=-y_max 283*906afcb8SAndy Fiddaman)) 284*906afcb8SAndy Fiddaman 285*906afcb8SAndy Fiddamancase "${mode}" in 286*906afcb8SAndy Fiddaman parallel) loop_parallel ; exit $? ;; 287*906afcb8SAndy Fiddaman serial) loop_serial ; exit $? ;; 288*906afcb8SAndy Fiddaman *) fatal_error $"Unknown mode \"${mode}\"." ;; 289*906afcb8SAndy Fiddamanesac 290*906afcb8SAndy Fiddaman 291*906afcb8SAndy Fiddamanfatal_error "not reached." 292*906afcb8SAndy Fiddaman# EOF. 293