17c2fbfb3SApril Chin#!/usr/bin/ksh93 27c2fbfb3SApril Chin 37c2fbfb3SApril Chin# 47c2fbfb3SApril Chin# CDDL HEADER START 57c2fbfb3SApril Chin# 67c2fbfb3SApril Chin# The contents of this file are subject to the terms of the 77c2fbfb3SApril Chin# Common Development and Distribution License (the "License"). 87c2fbfb3SApril Chin# You may not use this file except in compliance with the License. 97c2fbfb3SApril Chin# 107c2fbfb3SApril Chin# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 117c2fbfb3SApril Chin# or http://www.opensolaris.org/os/licensing. 127c2fbfb3SApril Chin# See the License for the specific language governing permissions 137c2fbfb3SApril Chin# and limitations under the License. 147c2fbfb3SApril Chin# 157c2fbfb3SApril Chin# When distributing Covered Code, include this CDDL HEADER in each 167c2fbfb3SApril Chin# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 177c2fbfb3SApril Chin# If applicable, add the following below this CDDL HEADER, with the 187c2fbfb3SApril Chin# fields enclosed by brackets "[]" replaced with your own identifying 197c2fbfb3SApril Chin# information: Portions Copyright [yyyy] [name of copyright owner] 207c2fbfb3SApril Chin# 217c2fbfb3SApril Chin# CDDL HEADER END 227c2fbfb3SApril Chin# 237c2fbfb3SApril Chin 247c2fbfb3SApril Chin# 25*3e14f97fSRoger A. Faulkner# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. 267c2fbfb3SApril Chin# 277c2fbfb3SApril Chin 287c2fbfb3SApril Chin# 297c2fbfb3SApril Chin# mandelbrotset1 - a simple mandelbrot set generation and 307c2fbfb3SApril Chin# parallel execution demo 317c2fbfb3SApril Chin# 327c2fbfb3SApril Chin 337c2fbfb3SApril Chin# Solaris needs /usr/xpg6/bin:/usr/xpg4/bin because the tools in /usr/bin are not POSIX-conformant 347c2fbfb3SApril Chinexport PATH=/usr/xpg6/bin:/usr/xpg4/bin:/bin:/usr/bin 357c2fbfb3SApril Chin 367c2fbfb3SApril Chin# Make sure all math stuff runs in the "C" locale to avoid problems 377c2fbfb3SApril Chin# with alternative # radix point representations (e.g. ',' instead of 387c2fbfb3SApril Chin# '.' in de_DE.*-locales). This needs to be set _before_ any 397c2fbfb3SApril Chin# floating-point constants are defined in this script). 407c2fbfb3SApril Chinif [[ "${LC_ALL}" != "" ]] ; then 417c2fbfb3SApril Chin export \ 427c2fbfb3SApril Chin LC_MONETARY="${LC_ALL}" \ 437c2fbfb3SApril Chin LC_MESSAGES="${LC_ALL}" \ 447c2fbfb3SApril Chin LC_COLLATE="${LC_ALL}" \ 457c2fbfb3SApril Chin LC_CTYPE="${LC_ALL}" 467c2fbfb3SApril Chin unset LC_ALL 477c2fbfb3SApril Chinfi 487c2fbfb3SApril Chinexport LC_NUMERIC=C 497c2fbfb3SApril Chin 507c2fbfb3SApril Chinfunction printmsg 517c2fbfb3SApril Chin{ 527c2fbfb3SApril Chin print -u2 "$*" 537c2fbfb3SApril Chin} 547c2fbfb3SApril Chin 557c2fbfb3SApril Chinfunction fatal_error 567c2fbfb3SApril Chin{ 577c2fbfb3SApril Chin print -u2 "${progname}: $*" 587c2fbfb3SApril Chin exit 1 597c2fbfb3SApril Chin} 607c2fbfb3SApril Chin 617c2fbfb3SApril Chin# Get terminal size and put values into a compound variable with the integer 627c2fbfb3SApril Chin# members "columns" and "lines" 637c2fbfb3SApril Chinfunction get_term_size 647c2fbfb3SApril Chin{ 657c2fbfb3SApril Chin nameref rect=$1 667c2fbfb3SApril Chin 677c2fbfb3SApril Chin rect.columns=${ tput cols ; } || return 1 687c2fbfb3SApril Chin rect.lines=${ tput lines ; } || return 1 697c2fbfb3SApril Chin 707c2fbfb3SApril Chin return 0 717c2fbfb3SApril Chin} 727c2fbfb3SApril Chin 737c2fbfb3SApril Chinfunction mandelbrot 747c2fbfb3SApril Chin{ 757c2fbfb3SApril Chin nameref result=$1 767c2fbfb3SApril Chin float x=$2 777c2fbfb3SApril Chin float y=$3 787c2fbfb3SApril Chin float xx 797c2fbfb3SApril Chin float yy 807c2fbfb3SApril Chin float x1=$4 817c2fbfb3SApril Chin float y1=$5 827c2fbfb3SApril Chin integer iteration=$6 837c2fbfb3SApril Chin integer max_iteration=$7 847c2fbfb3SApril Chin float mag 857c2fbfb3SApril Chin 867c2fbfb3SApril Chin for (( mag=0 ; mag < max_mag && iteration < max_iteration ; iteration++ )) ; do 877c2fbfb3SApril Chin (( 887c2fbfb3SApril Chin xx=x*x , 897c2fbfb3SApril Chin yy=y*y , 907c2fbfb3SApril Chin mag=xx+yy , 917c2fbfb3SApril Chin y=x*y*2+y1 , 927c2fbfb3SApril Chin x=xx-yy+x1 937c2fbfb3SApril Chin )) 947c2fbfb3SApril Chin done 957c2fbfb3SApril Chin 967c2fbfb3SApril Chin (( result=iteration )) 977c2fbfb3SApril Chin 987c2fbfb3SApril Chin return 0 997c2fbfb3SApril Chin} 1007c2fbfb3SApril Chin 1017c2fbfb3SApril Chin# build mandelbrot image serially 1027c2fbfb3SApril Chinfunction loop_serial 1037c2fbfb3SApril Chin{ 1047c2fbfb3SApril Chin integer value 10534f9b3eeSRoland Mainz typeset line="" 1067c2fbfb3SApril Chin 1077c2fbfb3SApril Chin for (( y=y_min ; y < y_max ; y+=stepwidth )) ; do 1087c2fbfb3SApril Chin for (( x=x_min ; x < x_max ; x+=stepwidth )) ; do 1097c2fbfb3SApril Chin mandelbrot value ${x} ${y} ${x} ${y} 1 ${symbollistlen} 11034f9b3eeSRoland Mainz line+="${symbollist:value:1}" 1117c2fbfb3SApril Chin done 1127c2fbfb3SApril Chin 11334f9b3eeSRoland Mainz line+=$'\n' 1147c2fbfb3SApril Chin done 1157c2fbfb3SApril Chin 11634f9b3eeSRoland Mainz print -r -- "${line}" 11734f9b3eeSRoland Mainz 1187c2fbfb3SApril Chin return 0 1197c2fbfb3SApril Chin} 1207c2fbfb3SApril Chin 1217c2fbfb3SApril Chin# build mandelbrot image using parallel worker jobs 1227c2fbfb3SApril Chinfunction loop_parallel 1237c2fbfb3SApril Chin{ 1247c2fbfb3SApril Chin integer numjobs=0 1257c2fbfb3SApril Chin # the following calculation suffers from rounding errors 1267c2fbfb3SApril Chin integer lines_per_job=$(( ((m_height+(numcpus-1)) / numcpus) )) 12734f9b3eeSRoland Mainz typeset tmpjobdir 1287c2fbfb3SApril Chin 1297c2fbfb3SApril Chin printmsg $"# lines_per_job=${lines_per_job}" 1307c2fbfb3SApril Chin printmsg $"# numcpus=${numcpus}" 1317c2fbfb3SApril Chin 1327c2fbfb3SApril Chin # "renice" worker jobs 1337c2fbfb3SApril Chin set -o bgnice 1347c2fbfb3SApril Chin 13534f9b3eeSRoland Mainz tmpjobdir="$(mktemp --default=/tmp --directory "mandelbrotset1${PPID}_$$_XXXXXX")" || fatal_error $"Could not create temporary directory." 13634f9b3eeSRoland Mainz trap "rm -r ${tmpjobdir}" EXIT # cleanup 1377c2fbfb3SApril Chin 1387c2fbfb3SApril Chin # try to generate a job identifer prefix which is unique across multiple hosts 1397c2fbfb3SApril Chin jobident="job_host_$(uname -n)pid_$$_ppid${PPID}" 1407c2fbfb3SApril Chin 1417c2fbfb3SApril Chin printmsg $"## prepare..." 1427c2fbfb3SApril Chin for (( y=y_min ; y < y_max ; y+=(stepwidth*lines_per_job) )) ; do 14334f9b3eeSRoland Mainz rm -f "${tmpjobdir}/${jobident}_child_$y.joboutput" 1447c2fbfb3SApril Chin 1457c2fbfb3SApril Chin (( numjobs++ )) 1467c2fbfb3SApril Chin done 1477c2fbfb3SApril Chin 1487c2fbfb3SApril Chin printmsg $"## running ${numjobs} children..." 1497c2fbfb3SApril Chin for (( y=y_min ; y < y_max ; y+=(stepwidth*lines_per_job) )) ; do 1507c2fbfb3SApril Chin ( 1517c2fbfb3SApril Chin integer value 15234f9b3eeSRoland Mainz typeset line="" 15334f9b3eeSRoland Mainz # save file name since we're going to modify "y" 15434f9b3eeSRoland Mainz typeset filename="${tmpjobdir}/${jobident}_child_$y.joboutput" 1557c2fbfb3SApril Chin 1567c2fbfb3SApril Chin for (( ; y < y_max && lines_per_job-- > 0 ; y+=stepwidth )) ; do 1577c2fbfb3SApril Chin for (( x=x_min ; x < x_max ; x+=stepwidth )) ; do 1587c2fbfb3SApril Chin mandelbrot value ${x} ${y} ${x} ${y} 1 ${symbollistlen} 15934f9b3eeSRoland Mainz line+="${symbollist:value:1}" 1607c2fbfb3SApril Chin done 1617c2fbfb3SApril Chin 16234f9b3eeSRoland Mainz line+=$'\n' 16334f9b3eeSRoland Mainz done 16434f9b3eeSRoland Mainz print -r -- "${line}" >"${filename}" 16534f9b3eeSRoland Mainz 16634f9b3eeSRoland Mainz exit 0 1677c2fbfb3SApril Chin ) & 1687c2fbfb3SApril Chin done 1697c2fbfb3SApril Chin 1707c2fbfb3SApril Chin printmsg $"## waiting for ${numjobs} children..." 1717c2fbfb3SApril Chin wait 1727c2fbfb3SApril Chin 1737c2fbfb3SApril Chin printmsg $"## output:" 1747c2fbfb3SApril Chin for (( y=y_min ; y < y_max ; y+=(stepwidth*lines_per_job) )) ; do 17534f9b3eeSRoland Mainz print -r -- "$( < "${tmpjobdir}/${jobident}_child_$y.joboutput")" 17634f9b3eeSRoland Mainz # EXIT trap will cleanup temporary files 1777c2fbfb3SApril Chin done 1787c2fbfb3SApril Chin 1797c2fbfb3SApril Chin return 0 1807c2fbfb3SApril Chin} 1817c2fbfb3SApril Chin 1827c2fbfb3SApril Chinfunction usage 1837c2fbfb3SApril Chin{ 1847c2fbfb3SApril Chin OPTIND=0 1857c2fbfb3SApril Chin getopts -a "${progname}" "${mandelbrotset1_usage}" OPT '-?' 1867c2fbfb3SApril Chin exit 2 1877c2fbfb3SApril Chin} 1887c2fbfb3SApril Chin 1897c2fbfb3SApril Chin# main 1907c2fbfb3SApril Chinbuiltin basename 1917c2fbfb3SApril Chinbuiltin cat 1927c2fbfb3SApril Chinbuiltin rm 1937c2fbfb3SApril Chinbuiltin uname # loop_parallel needs the ksh93 builtin version to generate unique job file names 19434f9b3eeSRoland Mainzbuiltin mktemp 19534f9b3eeSRoland Mainz 19634f9b3eeSRoland Mainzset -o noglob 19734f9b3eeSRoland Mainzset -o nounset 1987c2fbfb3SApril Chin 1997c2fbfb3SApril Chintypeset progname="${ basename "${0}" ; }" 2007c2fbfb3SApril Chin 2017c2fbfb3SApril Chinfloat x_max 2027c2fbfb3SApril Chinfloat x_min 2037c2fbfb3SApril Chinfloat y_max 2047c2fbfb3SApril Chinfloat y_min 2057c2fbfb3SApril Chinfloat m_width 2067c2fbfb3SApril Chinfloat m_height 2077c2fbfb3SApril Chinfloat max_mag 2087c2fbfb3SApril Chinfloat stepwidth 2097c2fbfb3SApril Chininteger numcpus 2107c2fbfb3SApril Chin 2117c2fbfb3SApril Chin# terminal size rect 21234f9b3eeSRoland Mainzcompound termsize=( 2137c2fbfb3SApril Chin integer columns=-1 2147c2fbfb3SApril Chin integer lines=-1 2157c2fbfb3SApril Chin) 2167c2fbfb3SApril Chin 2177c2fbfb3SApril Chinget_term_size termsize || fatal_error $"Could not get terminal size." 2187c2fbfb3SApril Chin 2197c2fbfb3SApril Chintypeset symbollist=' .:0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ%#' 2207c2fbfb3SApril Chintypeset symbollistlen=$(( ${#symbollist} - 1)) 2217c2fbfb3SApril Chintypeset mode="parallel" 2227c2fbfb3SApril Chin 223*3e14f97fSRoger A. Faulkner(( max_mag=400 )) 224*3e14f97fSRoger A. Faulkner(( stepwidth=0.1 )) 225*3e14f97fSRoger A. Faulkner 226*3e14f97fSRoger A. Faulkner# calculate number of worker CPUs and use 3 as fallback 227*3e14f97fSRoger A. Faulkner(( numcpus=$(getconf NPROCESSORS_ONLN || print "3") )) 228*3e14f97fSRoger A. Faulkner(( numcpus=numcpus*4 )) 2297c2fbfb3SApril Chin 2307c2fbfb3SApril Chin(( m_width=termsize.columns-1 , m_height=termsize.lines-2 )) 2317c2fbfb3SApril Chin 2327c2fbfb3SApril Chintypeset -r mandelbrotset1_usage=$'+ 233*3e14f97fSRoger A. Faulkner[-?\n@(#)\$Id: mandelbrotset1 (Roland Mainz) 2010-03-31 \$\n] 2347c2fbfb3SApril Chin[-author?Roland Mainz <roland.mainz@nrubsig.org>] 2357c2fbfb3SApril Chin[+NAME?mandelbrotset1 - generate mandelbrot set fractals with ksh93] 2367c2fbfb3SApril Chin[+DESCRIPTION?\bmandelbrotset1\b mandelbrot set fractal generator 2377c2fbfb3SApril Chin which runs either in serial or parallel mode (using multiple worker jobs).] 2387c2fbfb3SApril Chin[w:width?Width of fractal.]:[width] 2397c2fbfb3SApril Chin[h:height?Height of fractal.]:[height] 2407c2fbfb3SApril Chin[s:symbols?Symbols to build the fractal from.]:[symbolstring] 2417c2fbfb3SApril Chin[m:mag?Magnification level.]:[magnificationlevel] 2427c2fbfb3SApril Chin[p:stepwidth?Width per step.]:[widthperstep] 2437c2fbfb3SApril Chin[S:serial?Run in serial mode.] 2447c2fbfb3SApril Chin[P:parallel?Run in parallel mode.] 2457c2fbfb3SApril Chin[M:mode?Execution mode.]:[mode] 2467c2fbfb3SApril Chin[C:numcpus?Number of processors used for parallel execution.]:[numcpus] 2477c2fbfb3SApril Chin[+SEE ALSO?\bjuliaset1\b(1), \bksh93\b(1)] 2487c2fbfb3SApril Chin' 2497c2fbfb3SApril Chin 2507c2fbfb3SApril Chinwhile getopts -a "${progname}" "${mandelbrotset1_usage}" OPT ; do 2517c2fbfb3SApril Chin# printmsg "## OPT=|${OPT}|, OPTARG=|${OPTARG}|" 2527c2fbfb3SApril Chin case ${OPT} in 2537c2fbfb3SApril Chin w) m_width="${OPTARG}" ;; 2547c2fbfb3SApril Chin h) m_height="${OPTARG}" ;; 2557c2fbfb3SApril Chin s) symbollist="${OPTARG}" ;; 2567c2fbfb3SApril Chin m) max_mag="${OPTARG}" ;; 2577c2fbfb3SApril Chin p) stepwidth="${OPTARG}" ;; 2587c2fbfb3SApril Chin S) mode="serial" ;; 25934f9b3eeSRoland Mainz +S) mode="parallel" ;; 2607c2fbfb3SApril Chin P) mode="parallel" ;; 26134f9b3eeSRoland Mainz +P) mode="serial" ;; 2627c2fbfb3SApril Chin M) mode="${OPTARG}" ;; 2637c2fbfb3SApril Chin C) numcpus="${OPTARG}" ;; 2647c2fbfb3SApril Chin *) usage ;; 2657c2fbfb3SApril Chin esac 2667c2fbfb3SApril Chindone 2677c2fbfb3SApril Chinshift $((OPTIND-1)) 2687c2fbfb3SApril Chin 2697c2fbfb3SApril Chinprintmsg "# width=${m_width}" 2707c2fbfb3SApril Chinprintmsg "# height=${m_height}" 2717c2fbfb3SApril Chinprintmsg "# max_mag=${max_mag}" 2727c2fbfb3SApril Chinprintmsg "# stepwidth=${stepwidth}" 2737c2fbfb3SApril Chinprintmsg "# symbollist='${symbollist}'" 2747c2fbfb3SApril Chinprintmsg "# mode=${mode}" 2757c2fbfb3SApril Chin 2767c2fbfb3SApril Chin(( symbollistlen=${#symbollist}-1 )) 2777c2fbfb3SApril Chin 2787c2fbfb3SApril Chin(( 2797c2fbfb3SApril Chin x_max=m_width*stepwidth/2. , 2807c2fbfb3SApril Chin x_min=-x_max , 2817c2fbfb3SApril Chin y_max=m_height*stepwidth/2. , 2827c2fbfb3SApril Chin y_min=-y_max 2837c2fbfb3SApril Chin)) 2847c2fbfb3SApril Chin 2857c2fbfb3SApril Chincase "${mode}" in 2867c2fbfb3SApril Chin parallel) loop_parallel ; exit $? ;; 2877c2fbfb3SApril Chin serial) loop_serial ; exit $? ;; 2887c2fbfb3SApril Chin *) fatal_error $"Unknown mode \"${mode}\"." ;; 2897c2fbfb3SApril Chinesac 2907c2fbfb3SApril Chin 2917c2fbfb3SApril Chinfatal_error "not reached." 2927c2fbfb3SApril Chin# EOF. 293