import io;
-main
-{
- printf("Hello world!");
-}
+
+printf("Hello world!");
From ketan at ci.uchicago.edu Tue Mar 3 12:58:25 2015
From: ketan at ci.uchicago.edu (ketan at ci.uchicago.edu)
Date: Tue, 3 Mar 2015 12:58:25 -0600 (CST)
Subject: [Swift-commit] r8382 - SwiftApps/subjobs/mpicatsnsleep
Message-ID: <20150303185825.658019D539@svn.ci.uchicago.edu>
Author: ketan
Date: 2015-03-03 12:58:25 -0600 (Tue, 03 Mar 2015)
New Revision: 8382
Added:
SwiftApps/subjobs/mpicatsnsleep/swift.conf
Modified:
SwiftApps/subjobs/mpicatsnsleep/catsnsleepmpi.swift
SwiftApps/subjobs/mpicatsnsleep/runcetus.sh
Log:
adding conf
Modified: SwiftApps/subjobs/mpicatsnsleep/catsnsleepmpi.swift
===================================================================
--- SwiftApps/subjobs/mpicatsnsleep/catsnsleepmpi.swift 2015-02-27 20:02:44 UTC (rev 8381)
+++ SwiftApps/subjobs/mpicatsnsleep/catsnsleepmpi.swift 2015-03-03 18:58:25 UTC (rev 8382)
@@ -7,9 +7,9 @@
file out[] This script splits itself into lines, where line i is in file Note that each It’s easy to launch these kinds of workloads on a cluster. If using a plain host list: File: Just run with: As shown, A shorter, equivalent form of that command sequence is: On a PBS system, run with: Many other systems are supported! A simplified version of the MapReduce model is to just compute many
things and assemble them together at the end. This script splits itself into lines, then reassembles the original
@@ -845,24 +871,21 @@
"/bin/echo" s @stdout=o;
}
-main
+string lines[] = file_lines(input("mtc2.swift"));
+file fragments[];
+foreach line,i in lines
{
- string lines[] = file_lines(input("mtc2.swift"));
- file fragments[];
- foreach line,i in lines
- {
- file y <sprintf("out-%i.txt",i)> = g(line);
- fragments[i] = y;
- }
- file result <"assembled.txt"> = cat(fragments);
-}
+ file y <sprintf("out-%i.txt",i)> = g(line);
+ fragments[i] = y;
+}
+file result <"assembled.txt"> = cat(fragments);
Note that leading whitespace is trimmed by This script computes the given
Fibonacci number: Run it as: File: This code runs the See this section for information about calling Python or Numpy:
Swift/T Guide: Python This section demonstrates a complete, concrete example of the
+static executable feature. First, compose a
+Swift script. File: Then, copy Turbine’s example manifest file and edit.
+This manifest has all comments removed for simplicity. File: Then, build: File:
+
+printf("Hello world!");
import io;
-main
-{
- printf("Hello world!");
-}
out-
i .txt
/bin/echo
is eligible to run concurrently. See
@@ -827,8 +819,42 @@
3. Reductions
+3. Running many tasks on a cluster
mtc/hosts.txt
+machine1.some.edu
+machine2.some.edu
+machine3.some.edu
+machine4.some.edu
+stc mtc1.swift
+turbine -f hosts.txt -n 4 mtc1.tic
turbine
accepts an MPI hosts file and number of
+processes, just like mpiexec
.
+swift-t -t:f hosts.txt -n 4 mtc1.swift
+swift-t -m pbs -n 4 mtc1.swift
4. Reductions
+file_lines()
, and cat()
is part of the Swift/T standard library in module unix
.4. Recursion
+5. Recursion
fib/run.sh
sort
invocations concurrently, limited only by
available processors and data dependencies.5. Python and Numpy
+6. Python and Numpy
7. Static executables
+static-exec/hello.swift
+import io;
+printf("HELLO");
static-exec/hello.manifest
+pkg_name = hello
+pkg_version = 0.1
+
+main_script = hello.tic
static-exec/build.sh
+#!/bin/bash
+set -eu
+
+# Obtain the Turbine build configuration variables
+TURBINE=/homes/wozniak/sfw/fusion/compute/turbine-static
+source ${TURBINE}/scripts/turbine-build-config.sh
+
+# Generate hello.tic
+stc hello.swift
+# Bundle hello.tic and Turbine into hello_main.c
+mkstatic.tcl hello.manifest -c hello_main.c
+
+# Compile hello_main.c and link as standalone, static executable
+CFLAGS=-std=gnu99
+gcc -c ${CFLAGS} ${TURBINE_INCLUDES} hello_main.c
+mpicc -static -o hello.x hello_main.o ${TURBINE_LIBS} ${TURBINE_RPATH}
When you unpack this file, you will have a directory examples/
.
+Change to this directory and source setup.sh
to obtain build
+settings.
You can use the clean.sh
scripts to clean up.
Note
|
-In many scripts, we use shell options set -ex . |
+We often use shell options set -eux . |
TCLLIBPATH
is space-separated (which makes for easier Tcl processing).TCLLIBPATH
is space-separated (which makes for easier Tcl
+processing).
+ Note
+ |
+TCLLIBPATH is modified by Turbine. To expose a Tcl package to
+Swift/T, set SWIFT_PATH . |
+
We create pkgIndex.tcl
from the shell:
import io;
import f;
-main
-{
- int x = 2;
- int y = 3;
- int z = f(x,y);
- printf("sum: %i", z);
-}
+
+int x = 2;
+int y = 3;
+int z = f(x,y);
+printf("sum: %i", z);
Now, make the package available to Turbine and run it:
#include <stdio.h>
+#include <unistd.h>
#include "g.h"
@@ -995,6 +1018,7 @@
printf("g: %i+%i=%i\n", i1, i2, sum);
printf("sleeping for %i seconds...\n", sum);
sleep(sum);
+ return sum;
}
This function is normally called as (test-g.c
):
It may be compiled and run with (test-g.sh
):
#!/bin/sh
+#!/bin/sh -ex
-gcc -c g.c || exit 1
-gcc -c test-g.c || exit 1
-gcc -o g.x test-g.o g.o || exit 1
+gcc -c g.c
+gcc -c test-g.c
+gcc -o g.x test-g.o g.o
./g.x
test-swig-g.sh
):rm *.o
-gcc -c -fPIC g.c &&
-gcc -c -fPIC -I /usr/include/tcl8.5 g_wrap.c &&
-gcc -shared -o libg.so g_wrap.o g.o &&
+#!/bin/sh
+rm -fv *.o
+set -ex
+gcc -c -fPIC -Wall g.c
+gcc -c -fPIC -I/home/wozniak/sfw/tcl-8.6.0/include g_wrap.c
+gcc -shared -o libg.so g_wrap.o g.o
tclsh make-package.tcl > pkgIndex.tcl
This produces libg.so
and the Tcl package file pkgIndex.tcl
.
@@ -1058,7 +1084,9 @@
> export TCLLIBPATH=$PWD
> tclsh test-g.tcl
g: 2+3=5
-sleeping for 5 seconds...
+sleeping for 5 seconds...
+
+te
Then, we bring the Tcl package into Swift (test-g-1.swift
):
@dispatch=WORKER
+import io;
+
+ at dispatch=WORKER
(int sum) g(int i1, int i2) "g" "0.0"
[ "set <<sum>> [ g <<i1>> <<i2>> ]" ];
-main {
- int sum = g(2, 3);
-}
+int sum = g(2, 3);
+printf("Swift: sum: %i", sum);
Compile and run (test-g-1.sh
):
Write a foreach loop around the call to g
(test-g-n.swift
):
@dispatch=WORKER
+import io;
+import stats;
+
+
+ at dispatch=WORKER
(int sum) g(int i1, int i2) "g" "0.0"
-[ "set <<sum>> [ g <<i1>> <<i2>> ]" ];
+ [ "set <<sum>> [ g <<i1>> <<i2>> ]" ];
-main {
- foreach i in [0:5] {
- int sum = g(i, 5-i);
- }
-}
+int d[];
+foreach i in [0:5] {
+ d[i] = g(i, 5-i);
+}
+
+y = sum_integer(d);
+printf("y: %i", y);
Compile and run (test-g-n.swift
):
import blob;
import io;
-main {
- file data = input_file("input.data");
- blob b = blob_read(data);
- float v[] = floats_from_blob(b);
- printf("size(v) = %i", size(v));
- printf("v[0]=%0.2f", v[0]);
- printf("v[last]=%0.2f", v[size(v)-1]);
-}
+file data = input_file("input.data");
+blob b = blob_read(data);
+float v[] = floats_from_blob(b);
+printf("size(v) = %i", size(v));
+printf("v[0]=%0.2f", v[0]);
+printf("v[last]=%0.2f", v[size(v)-1]);
test-b-simple.sh
:
rm *.o
-swig -module b b.h
+swig -module b b.i
gcc -c -fPIC b.c
-gcc -c -fPIC -I /usr/include/tcl8.5 b_wrap.c
+gcc -c -fPIC $TCL_INCLUDE_SPEC b_wrap.c
gcc -shared -o libb.so b_wrap.o b.o
tclsh make-package.tcl > pkgIndex.tcl
test-b-swift.sh
:
This example will demonstrate multiplying y=A*x
using Swift to call
a user Fortran library, which in turn calls the BLAS function
dgemv
. This demonstrates the generality of our model.
In these scripts, you must have the BLAS archive. Change the +appropriate shell variable to point to this file.
It is built and run with (test-mvm.sh
):
#!/bin/bash
+#!/bin/bash -eu
# Note Fortran memory layout:
turbine-write-doubles A.data 1 3 2 4
turbine-write-doubles x.data 5 6
-BLAS="$HOME/Downloads/BLAS/blas_LINUX.a"
-gfortran -c MVM.f &&
-gfortran -c test-MVM.f &&
-gfortran -o test-MVM.x test-MVM.o MVM.o $BLAS || exit 1
+gfortran -c mvm.f
+gfortran -c test-mvm.f
+gfortran -o test-mvm.x test-mvm.o mvm.o ${BLAS}
-./test-MVM.x
+./test-mvm.x
FortWrap will scan mvm.f
and produce the C++ files FortFuncs.h
and
FortFuncs.cpp
, which we wrap with SWIG to produce a Tcl function
@@ -1413,15 +1445,13 @@
(blob y) mvm_blob(blob A, blob x, int n) "mvm" "0.0"
[ "set <<y>> [ mvm::mvm <<A>> <<x>> <<n>> ]" ];
-main {
- int n = 2;
- blob A_blob = blob_read(input_file("A.data"));
- blob x_blob = blob_read(input_file("x.data"));
- blob y_blob = mvm_blob(A_blob, x_blob, n);
- float y[] = floats_from_blob(y_blob);
- foreach v, i in y {
- printf("y[%i]=%f", i, v);
- }
+int n = 2;
+blob A_blob = blob_read(input_file("A.data"));
+blob x_blob = blob_read(input_file("x.data"));
+blob y_blob = mvm_blob(A_blob, x_blob, n);
+float y[] = floats_from_blob(y_blob);
+foreach v, i in y {
+ printf("y[%i]=%f", i, v);
}
Our Tcl wrapper converts the Tcl call to mvm
on blob arguments
@@ -1433,17 +1463,12 @@
Now, we build everything (build.sh
):
#!/bin/bash -e
+#!/bin/bash -eu
TURBINE=$( which turbine )
TURBINE_HOME=$( dirname $( dirname ${TURBINE} ) )
source ${TURBINE_HOME}/scripts/turbine-config.sh
-set -x
-
-BLAS="$HOME/Downloads/BLAS/blas_LINUX.a"
-TCL_INCLUDE=${TCL}/include
-
# Wrap the Fortran in C++
fortwrap.py --array-as-ptr --no-vector --no-fmat mvm.f
# Wrap the C++ in Tcl
@@ -1453,7 +1478,7 @@
# Compile everything
g++ -c -fPIC -I . FortFuncs.cpp
-g++ -c -fPIC -I ${TCL_INCLUDE} FortFuncs_wrap.cxx
+g++ -c -fPIC ${TCL_INCLUDE_SPEC} FortFuncs_wrap.cxx
gfortran -c -fPIC mvm.f
# Build the shared object
@@ -1465,12 +1490,9 @@
We run it in Swift with (test-mvm-swift.sh
):
-#!/bin/bash
+#!/bin/sh
-stc test-mvm.swift test-mvm.tcl
-
-export TURBINE_USER_LIB=$PWD
-turbine test-mvm.tcl
+swift-t -r $PWD test-mvm.swift
This produces:
@@ -1487,52 +1509,61 @@
case that the Swift program will construct an array of strings to pass
to the C code. The C program is minimally modified by
renaming its main()
function and calling that from Swift/T.
-Consider the user code (swift-main.c
):
+Consider the user code (main.c
):
#include <stdio.h>
-#include "swift-main.h"
-int swift_main(int argc, char* argv[]) {
+#include "main.h"
+int main(int argc, char* argv[]) {
for (int i = 0; i < argc; i++)
printf("arg[%i]: %s\n", i, argv[i]);
return 0;
}
-This is essentially a simple C program except that its main()
function
-has been renamed to swift_main()
. Also, the header swift-main.h
-has been created to allow the Swift/T framework to call this code.
-The function essentially acts like /bin/echo
, reporting its
+
The function essentially acts like /bin/echo
, reporting its
arguments.
-An example C wrapper to call this function is as follows (prog-c.c
):
+Consider the user code (main_leaf.c
):
-#include "swift-main.h"
-int main(int argc, char* argv[]) {
- swift_main(argc, argv);
+#include <stdio.h>
+#include "main.h"
+int main_leaf(int argc, char** argv) {
+ for (int i = 0; i < argc; i++)
+ printf("arg[%i]: %s\n", i, argv[i]);
return 0;
}
-The equivalent Swift code is as follows (prog-swift.swift
):
+This is essentially the same program except that its main()
function
+has been renamed to swift_main()
. Also, the header swift-main.h
+has been created to allow the Swift/T framework to call this code.
+The Swift/T distribution comes with functionality to make this easy to
+call. The key program is genleaf
.
+The equivalent Swift code is as follows (test-main.swift
):
import io;
-(int v) swift_main(string A[]) "swift_main" "0.0" "swift_main_wrap";
-main {
- string A[] = [ "arg1", "arg2", "arg3" ];
- rc = swift_main(A);
- printf("exit code: %i", rc);
-}
+
+mainapp;
+
+printf("Swift...");
+string A[] = [ "arg1", "arg2", "arg3" ];
+rc = main_leaf(A);
+printf("exit code: %i", rc);
The Swift version defines the extension function symbol swift_main
,
then calls it with the given array of strings. The "exit code"
(actually just a return value) is available to Swift.
This example may be compiled and run (from C, Tcl, and Swift) by using
the provided Makefile.
-The above process is semi-automated by the genleaf
script. The script takes a C program and a header file as input and produces the required Tcl-C extension and Tcl leaf function. It also produces a simple source Swift and stc-compiled Tcl code ready to be run via turbine
. Invoke genleaf
as follows:
+The above process is semi-automated by the genleaf
script. The
+script takes a C program and a header file as input and produces the
+required Tcl-C extension and Tcl leaf function. It also produces a
+simple source Swift and stc-compiled Tcl code ready to be run via
+turbine
. Invoke genleaf
as follows (test-main.sh
):
-./genleaf ex2.c ex2.h
-turbine user-code.tcl
+genleaf -vv main.c main.h test-main.swift
+swift-t -r $PWD user-code.swift
@@ -1614,8 +1645,8 @@
-export TURBINE_USER_LIB=$PWD
-turbine prog-swift.tcl
+make
+swift-t -r $PWD prog-swift.swift
@@ -1691,12 +1722,10 @@
(int o) f(int i1, int i2) "my_pkg" "0.0" "f";
-main {
- int x = 2;
- int y = 3;
- int z = f(x,y);
- printf("sum: %i", z);
-}
+int x = 2;
+int y = 3;
+int z = f(x,y);
+printf("sum: %i", z);
For more information about the APIs used to store/retrieve Swift/T
data and issue rules, see Turbine
@@ -1721,9 +1750,11 @@
+float z = @par=2 f(3);
+printf("z: %0.3f", z);
double
f(MPI_Comm comm, int k)
{
+ printf("f()\n");
int task_rank, task_size;
MPI_Comm_rank(comm, &task_rank);
MPI_Comm_size(comm, &task_size);
+ printf("In f(): rank: %i/%i\n", task_rank, task_size);
MPI_Barrier(comm);
sleep(task_rank);
MPI_Barrier(comm);
@@ -1749,11 +1780,8 @@
@par @dispatch=WORKER (float z) f(int k) "f" "0.0" "f_tcl";
-main
-{
- float z = @par=2 f(3);
- printf("z: %0.3f", z);
-}
In the declaration, @par
allows us to call the function as a
parallel function. At call time, we use @par=2
.
The controller MPI program is run as: (run.sh
):
Swift/T has a powerful shell interface in its +app function syntax. Here are some +advanced examples:
To pass a whole command line into a generic app function, use:
File: sh-c/sh-1.swift
import string;
+app f(string commandline)
+{
+ "sh" "-c" commandline;
+}
+tokens = ["/bin/echo","this","is","my","message"];
+f(string_join(tokens," "));
+producing:
this is my message
+Programs that are found in different locations on different machines +can be accessed like this:
File: sh-c/sh-2.swift
import string;
+import sys;
+
+// Program configuration
+string program;
+if (getenv("HOST") == "umbra")
+{
+ program = "/bin/echo";
+}
+else
+{
+ // something else
+}
+// End program configuration
+
+app f(string arguments)
+{
+ program arguments;
+}
+tokens = ["this","is","my","message"];
+f(string_join(tokens," "));
+You can put the "program configuration" section in a separate file and
+import
it.
If you prefer, you could also put separate definitions of program
in
+separate files and conditionally #include
+them with STC support for the C preprocessor.
This script converts itself to octal in mtc.octal
.
File: mtc/mtc1.swift
A shorter, equivalent form of that command sequence is:
swift-t -t:f hosts.txt -n 4 mtc1.swift
+swift-t -t f:hosts.txt -n 4 mtc1.swift
On a PBS system, run with:
STC runs as a Java program. You may use -j
to set the Java VM
executable. This Java VM must be compatible with the javac
used to
compile STC.
By default, STC runs the user script through the C preprocessor +
By default, STC runs the user script through the C preprocessor
(cpp
), enabling arbitrary macro processing, etc. The -D
, -E
,
-I
, and -p
options are relevant to this feature.
Additional arguments for advanced users/developers:
Swift has a module system that allows you to import function and variable definitions into your source file. Importing a module will import all @@ -3899,7 +3900,7 @@
Disable logging. TURBINE_LOG=1
or unset enables
logging, assuming logging was not disabled at configure time. Logging
-goes to tandard output by default.
+goes to standard output by default.