[Swift-commit] r8041 - www/Swift-T
wozniak at ci.uchicago.edu
wozniak at ci.uchicago.edu
Fri Jul 18 15:58:34 CDT 2014
Author: wozniak
Date: 2014-07-18 15:58:34 -0500 (Fri, 18 Jul 2014)
New Revision: 8041
Added:
www/Swift-T/leaf.html
Log:
Adding Swift-T/leaf.html
Added: www/Swift-T/leaf.html
===================================================================
--- www/Swift-T/leaf.html (rev 0)
+++ www/Swift-T/leaf.html 2014-07-18 20:58:34 UTC (rev 8041)
@@ -0,0 +1,1885 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
+<meta name="generator" content="AsciiDoc 8.6.9" />
+<title>Swift/T Leaf Function Guide</title>
+<style type="text/css">
+/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
+
+/* Default font. */
+body {
+ font-family: Georgia,serif;
+}
+
+/* Title font. */
+h1, h2, h3, h4, h5, h6,
+div.title, caption.title,
+thead, p.table.header,
+#toctitle,
+#author, #revnumber, #revdate, #revremark,
+#footer {
+ font-family: Arial,Helvetica,sans-serif;
+}
+
+body {
+ margin: 1em 5% 1em 5%;
+}
+
+a {
+ color: blue;
+ text-decoration: underline;
+}
+a:visited {
+ color: fuchsia;
+}
+
+em {
+ font-style: italic;
+ color: navy;
+}
+
+strong {
+ font-weight: bold;
+ color: #083194;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ color: #527bbd;
+ margin-top: 1.2em;
+ margin-bottom: 0.5em;
+ line-height: 1.3;
+}
+
+h1, h2, h3 {
+ border-bottom: 2px solid silver;
+}
+h2 {
+ padding-top: 0.5em;
+}
+h3 {
+ float: left;
+}
+h3 + * {
+ clear: left;
+}
+h5 {
+ font-size: 1.0em;
+}
+
+div.sectionbody {
+ margin-left: 0;
+}
+
+hr {
+ border: 1px solid silver;
+}
+
+p {
+ margin-top: 0.5em;
+ margin-bottom: 0.5em;
+}
+
+ul, ol, li > p {
+ margin-top: 0;
+}
+ul > li { color: #aaa; }
+ul > li > * { color: black; }
+
+.monospaced, code, pre {
+ font-family: "Courier New", Courier, monospace;
+ font-size: inherit;
+ color: navy;
+ padding: 0;
+ margin: 0;
+}
+pre {
+ white-space: pre-wrap;
+}
+
+#author {
+ color: #527bbd;
+ font-weight: bold;
+ font-size: 1.1em;
+}
+#email {
+}
+#revnumber, #revdate, #revremark {
+}
+
+#footer {
+ font-size: small;
+ border-top: 2px solid silver;
+ padding-top: 0.5em;
+ margin-top: 4.0em;
+}
+#footer-text {
+ float: left;
+ padding-bottom: 0.5em;
+}
+#footer-badges {
+ float: right;
+ padding-bottom: 0.5em;
+}
+
+#preamble {
+ margin-top: 1.5em;
+ margin-bottom: 1.5em;
+}
+div.imageblock, div.exampleblock, div.verseblock,
+div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
+div.admonitionblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+div.admonitionblock {
+ margin-top: 2.0em;
+ margin-bottom: 2.0em;
+ margin-right: 10%;
+ color: #606060;
+}
+
+div.content { /* Block element content. */
+ padding: 0;
+}
+
+/* Block element titles. */
+div.title, caption.title {
+ color: #527bbd;
+ font-weight: bold;
+ text-align: left;
+ margin-top: 1.0em;
+ margin-bottom: 0.5em;
+}
+div.title + * {
+ margin-top: 0;
+}
+
+td div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content div.title:first-child {
+ margin-top: 0.0em;
+}
+div.content + div.title {
+ margin-top: 0.0em;
+}
+
+div.sidebarblock > div.content {
+ background: #ffffee;
+ border: 1px solid #dddddd;
+ border-left: 4px solid #f0f0f0;
+ padding: 0.5em;
+}
+
+div.listingblock > div.content {
+ border: 1px solid #dddddd;
+ border-left: 5px solid #f0f0f0;
+ background: #f8f8f8;
+ padding: 0.5em;
+}
+
+div.quoteblock, div.verseblock {
+ padding-left: 1.0em;
+ margin-left: 1.0em;
+ margin-right: 10%;
+ border-left: 5px solid #f0f0f0;
+ color: #888;
+}
+
+div.quoteblock > div.attribution {
+ padding-top: 0.5em;
+ text-align: right;
+}
+
+div.verseblock > pre.content {
+ font-family: inherit;
+ font-size: inherit;
+}
+div.verseblock > div.attribution {
+ padding-top: 0.75em;
+ text-align: left;
+}
+/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
+div.verseblock + div.attribution {
+ text-align: left;
+}
+
+div.admonitionblock .icon {
+ vertical-align: top;
+ font-size: 1.1em;
+ font-weight: bold;
+ text-decoration: underline;
+ color: #527bbd;
+ padding-right: 0.5em;
+}
+div.admonitionblock td.content {
+ padding-left: 0.5em;
+ border-left: 3px solid #dddddd;
+}
+
+div.exampleblock > div.content {
+ border-left: 3px solid #dddddd;
+ padding-left: 0.5em;
+}
+
+div.imageblock div.content { padding-left: 0; }
+span.image img { border-style: none; vertical-align: text-bottom; }
+a.image:visited { color: white; }
+
+dl {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+dt {
+ margin-top: 0.5em;
+ margin-bottom: 0;
+ font-style: normal;
+ color: navy;
+}
+dd > *:first-child {
+ margin-top: 0.1em;
+}
+
+ul, ol {
+ list-style-position: outside;
+}
+ol.arabic {
+ list-style-type: decimal;
+}
+ol.loweralpha {
+ list-style-type: lower-alpha;
+}
+ol.upperalpha {
+ list-style-type: upper-alpha;
+}
+ol.lowerroman {
+ list-style-type: lower-roman;
+}
+ol.upperroman {
+ list-style-type: upper-roman;
+}
+
+div.compact ul, div.compact ol,
+div.compact p, div.compact p,
+div.compact div, div.compact div {
+ margin-top: 0.1em;
+ margin-bottom: 0.1em;
+}
+
+tfoot {
+ font-weight: bold;
+}
+td > div.verse {
+ white-space: pre;
+}
+
+div.hdlist {
+ margin-top: 0.8em;
+ margin-bottom: 0.8em;
+}
+div.hdlist tr {
+ padding-bottom: 15px;
+}
+dt.hdlist1.strong, td.hdlist1.strong {
+ font-weight: bold;
+}
+td.hdlist1 {
+ vertical-align: top;
+ font-style: normal;
+ padding-right: 0.8em;
+ color: navy;
+}
+td.hdlist2 {
+ vertical-align: top;
+}
+div.hdlist.compact tr {
+ margin: 0;
+ padding-bottom: 0;
+}
+
+.comment {
+ background: yellow;
+}
+
+.footnote, .footnoteref {
+ font-size: 0.8em;
+}
+
+span.footnote, span.footnoteref {
+ vertical-align: super;
+}
+
+#footnotes {
+ margin: 20px 0 20px 0;
+ padding: 7px 0 0 0;
+}
+
+#footnotes div.footnote {
+ margin: 0 0 5px 0;
+}
+
+#footnotes hr {
+ border: none;
+ border-top: 1px solid silver;
+ height: 1px;
+ text-align: left;
+ margin-left: 0;
+ width: 20%;
+ min-width: 100px;
+}
+
+div.colist td {
+ padding-right: 0.5em;
+ padding-bottom: 0.3em;
+ vertical-align: top;
+}
+div.colist td img {
+ margin-top: 0.3em;
+}
+
+ at media print {
+ #footer-badges { display: none; }
+}
+
+#toc {
+ margin-bottom: 2.5em;
+}
+
+#toctitle {
+ color: #527bbd;
+ font-size: 1.1em;
+ font-weight: bold;
+ margin-top: 1.0em;
+ margin-bottom: 0.1em;
+}
+
+div.toclevel0, div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+div.toclevel2 {
+ margin-left: 2em;
+ font-size: 0.9em;
+}
+div.toclevel3 {
+ margin-left: 4em;
+ font-size: 0.9em;
+}
+div.toclevel4 {
+ margin-left: 6em;
+ font-size: 0.9em;
+}
+
+span.aqua { color: aqua; }
+span.black { color: black; }
+span.blue { color: blue; }
+span.fuchsia { color: fuchsia; }
+span.gray { color: gray; }
+span.green { color: green; }
+span.lime { color: lime; }
+span.maroon { color: maroon; }
+span.navy { color: navy; }
+span.olive { color: olive; }
+span.purple { color: purple; }
+span.red { color: red; }
+span.silver { color: silver; }
+span.teal { color: teal; }
+span.white { color: white; }
+span.yellow { color: yellow; }
+
+span.aqua-background { background: aqua; }
+span.black-background { background: black; }
+span.blue-background { background: blue; }
+span.fuchsia-background { background: fuchsia; }
+span.gray-background { background: gray; }
+span.green-background { background: green; }
+span.lime-background { background: lime; }
+span.maroon-background { background: maroon; }
+span.navy-background { background: navy; }
+span.olive-background { background: olive; }
+span.purple-background { background: purple; }
+span.red-background { background: red; }
+span.silver-background { background: silver; }
+span.teal-background { background: teal; }
+span.white-background { background: white; }
+span.yellow-background { background: yellow; }
+
+span.big { font-size: 2em; }
+span.small { font-size: 0.6em; }
+
+span.underline { text-decoration: underline; }
+span.overline { text-decoration: overline; }
+span.line-through { text-decoration: line-through; }
+
+div.unbreakable { page-break-inside: avoid; }
+
+
+/*
+ * xhtml11 specific
+ *
+ * */
+
+div.tableblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+div.tableblock > table {
+ border: 3px solid #527bbd;
+}
+thead, p.table.header {
+ font-weight: bold;
+ color: #527bbd;
+}
+p.table {
+ margin-top: 0;
+}
+/* Because the table frame attribute is overriden by CSS in most browsers. */
+div.tableblock > table[frame="void"] {
+ border-style: none;
+}
+div.tableblock > table[frame="hsides"] {
+ border-left-style: none;
+ border-right-style: none;
+}
+div.tableblock > table[frame="vsides"] {
+ border-top-style: none;
+ border-bottom-style: none;
+}
+
+
+/*
+ * html5 specific
+ *
+ * */
+
+table.tableblock {
+ margin-top: 1.0em;
+ margin-bottom: 1.5em;
+}
+thead, p.tableblock.header {
+ font-weight: bold;
+ color: #527bbd;
+}
+p.tableblock {
+ margin-top: 0;
+}
+table.tableblock {
+ border-width: 3px;
+ border-spacing: 0px;
+ border-style: solid;
+ border-color: #527bbd;
+ border-collapse: collapse;
+}
+th.tableblock, td.tableblock {
+ border-width: 1px;
+ padding: 4px;
+ border-style: solid;
+ border-color: #527bbd;
+}
+
+table.tableblock.frame-topbot {
+ border-left-style: hidden;
+ border-right-style: hidden;
+}
+table.tableblock.frame-sides {
+ border-top-style: hidden;
+ border-bottom-style: hidden;
+}
+table.tableblock.frame-none {
+ border-style: hidden;
+}
+
+th.tableblock.halign-left, td.tableblock.halign-left {
+ text-align: left;
+}
+th.tableblock.halign-center, td.tableblock.halign-center {
+ text-align: center;
+}
+th.tableblock.halign-right, td.tableblock.halign-right {
+ text-align: right;
+}
+
+th.tableblock.valign-top, td.tableblock.valign-top {
+ vertical-align: top;
+}
+th.tableblock.valign-middle, td.tableblock.valign-middle {
+ vertical-align: middle;
+}
+th.tableblock.valign-bottom, td.tableblock.valign-bottom {
+ vertical-align: bottom;
+}
+
+
+/*
+ * manpage specific
+ *
+ * */
+
+body.manpage h1 {
+ padding-top: 0.5em;
+ padding-bottom: 0.5em;
+ border-top: 2px solid silver;
+ border-bottom: 2px solid silver;
+}
+body.manpage h2 {
+ border-style: none;
+}
+body.manpage div.sectionbody {
+ margin-left: 3em;
+}
+
+ at media print {
+ body.manpage div#toc { display: none; }
+}
+
+
+
+/* SWIFT/T GUIDE CUSTOMIZATIONS */
+
+a:visited {
+ color: gray;
+}
+h5 {
+ font-size: 0.8em;
+}
+
+</style>
+<script type="text/javascript">
+/*<![CDATA[*/
+var asciidoc = { // Namespace.
+
+/////////////////////////////////////////////////////////////////////
+// Table Of Contents generator
+/////////////////////////////////////////////////////////////////////
+
+/* Author: Mihai Bazon, September 2002
+ * http://students.infoiasi.ro/~mishoo
+ *
+ * Table Of Content generator
+ * Version: 0.4
+ *
+ * Feel free to use this script under the terms of the GNU General Public
+ * License, as long as you do not remove or alter this notice.
+ */
+
+ /* modified by Troy D. Hanson, September 2006. License: GPL */
+ /* modified by Stuart Rackham, 2006, 2009. License: GPL */
+
+// toclevels = 1..4.
+toc: function (toclevels) {
+
+ function getText(el) {
+ var text = "";
+ for (var i = el.firstChild; i != null; i = i.nextSibling) {
+ if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
+ text += i.data;
+ else if (i.firstChild != null)
+ text += getText(i);
+ }
+ return text;
+ }
+
+ function TocEntry(el, text, toclevel) {
+ this.element = el;
+ this.text = text;
+ this.toclevel = toclevel;
+ }
+
+ function tocEntries(el, toclevels) {
+ var result = new Array;
+ var re = new RegExp('[hH]([1-'+(toclevels+1)+'])');
+ // Function that scans the DOM tree for header elements (the DOM2
+ // nodeIterator API would be a better technique but not supported by all
+ // browsers).
+ var iterate = function (el) {
+ for (var i = el.firstChild; i != null; i = i.nextSibling) {
+ if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
+ var mo = re.exec(i.tagName);
+ if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
+ result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
+ }
+ iterate(i);
+ }
+ }
+ }
+ iterate(el);
+ return result;
+ }
+
+ var toc = document.getElementById("toc");
+ if (!toc) {
+ return;
+ }
+
+ // Delete existing TOC entries in case we're reloading the TOC.
+ var tocEntriesToRemove = [];
+ var i;
+ for (i = 0; i < toc.childNodes.length; i++) {
+ var entry = toc.childNodes[i];
+ if (entry.nodeName.toLowerCase() == 'div'
+ && entry.getAttribute("class")
+ && entry.getAttribute("class").match(/^toclevel/))
+ tocEntriesToRemove.push(entry);
+ }
+ for (i = 0; i < tocEntriesToRemove.length; i++) {
+ toc.removeChild(tocEntriesToRemove[i]);
+ }
+
+ // Rebuild TOC entries.
+ var entries = tocEntries(document.getElementById("content"), toclevels);
+ for (var i = 0; i < entries.length; ++i) {
+ var entry = entries[i];
+ if (entry.element.id == "")
+ entry.element.id = "_toc_" + i;
+ var a = document.createElement("a");
+ a.href = "#" + entry.element.id;
+ a.appendChild(document.createTextNode(entry.text));
+ var div = document.createElement("div");
+ div.appendChild(a);
+ div.className = "toclevel" + entry.toclevel;
+ toc.appendChild(div);
+ }
+ if (entries.length == 0)
+ toc.parentNode.removeChild(toc);
+},
+
+
+/////////////////////////////////////////////////////////////////////
+// Footnotes generator
+/////////////////////////////////////////////////////////////////////
+
+/* Based on footnote generation code from:
+ * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
+ */
+
+footnotes: function () {
+ // Delete existing footnote entries in case we're reloading the footnodes.
+ var i;
+ var noteholder = document.getElementById("footnotes");
+ if (!noteholder) {
+ return;
+ }
+ var entriesToRemove = [];
+ for (i = 0; i < noteholder.childNodes.length; i++) {
+ var entry = noteholder.childNodes[i];
+ if (entry.nodeName.toLowerCase() == 'div' && entry.getAttribute("class") == "footnote")
+ entriesToRemove.push(entry);
+ }
+ for (i = 0; i < entriesToRemove.length; i++) {
+ noteholder.removeChild(entriesToRemove[i]);
+ }
+
+ // Rebuild footnote entries.
+ var cont = document.getElementById("content");
+ var spans = cont.getElementsByTagName("span");
+ var refs = {};
+ var n = 0;
+ for (i=0; i<spans.length; i++) {
+ if (spans[i].className == "footnote") {
+ n++;
+ var note = spans[i].getAttribute("data-note");
+ if (!note) {
+ // Use [\s\S] in place of . so multi-line matches work.
+ // Because JavaScript has no s (dotall) regex flag.
+ note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
+ spans[i].innerHTML =
+ "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
+ "' title='View footnote' class='footnote'>" + n + "</a>]";
+ spans[i].setAttribute("data-note", note);
+ }
+ noteholder.innerHTML +=
+ "<div class='footnote' id='_footnote_" + n + "'>" +
+ "<a href='#_footnoteref_" + n + "' title='Return to text'>" +
+ n + "</a>. " + note + "</div>";
+ var id =spans[i].getAttribute("id");
+ if (id != null) refs["#"+id] = n;
+ }
+ }
+ if (n == 0)
+ noteholder.parentNode.removeChild(noteholder);
+ else {
+ // Process footnoterefs.
+ for (i=0; i<spans.length; i++) {
+ if (spans[i].className == "footnoteref") {
+ var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
+ href = href.match(/#.*/)[0]; // Because IE return full URL.
+ n = refs[href];
+ spans[i].innerHTML =
+ "[<a href='#_footnote_" + n +
+ "' title='View footnote' class='footnote'>" + n + "</a>]";
+ }
+ }
+ }
+},
+
+install: function(toclevels) {
+ var timerId;
+
+ function reinstall() {
+ asciidoc.footnotes();
+ if (toclevels) {
+ asciidoc.toc(toclevels);
+ }
+ }
+
+ function reinstallAndRemoveTimer() {
+ clearInterval(timerId);
+ reinstall();
+ }
+
+ timerId = setInterval(reinstall, 500);
+ if (document.addEventListener)
+ document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);
+ else
+ window.onload = reinstallAndRemoveTimer;
+}
+
+}
+asciidoc.install(2);
+/*]]>*/
+</script>
+</head>
+<body class="article" style="max-width:750px">
+<div id="header">
+<h1>Swift/T Leaf Function Guide</h1>
+<div id="toc">
+ <div id="toctitle">Table of Contents</div>
+ <noscript><p><b>JavaScript must be enabled in your browser to display the table of contents.</b></p></noscript>
+</div>
+</div>
+<div id="content">
+<div id="preamble">
+<div class="sectionbody">
+<div class="paragraph"><p>This page documents the methods available to connect Swift/T to
+leaf tasks that may be C, C++, or Fortran functions (native code).</p></div>
+<div class="paragraph"><p>Links:</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+<a href=":swift.html">General documentation for Swift/T</a>
+</p>
+</li>
+<li>
+<p>
+<a href="http://www.tcl.tk">Tcl documentation</a>
+</p>
+</li>
+<li>
+<p>
+<a href="http://www.swig.or">SWIG</a>
+</p>
+</li>
+</ul></div>
+<div class="paragraph"><p>To report problems with these examples, post to
+<a href="http://lists.mcs.anl.gov/mailman/listinfo/exm-user">the ExM user list</a>.</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_overview">1. Overview</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Two methods are available for connecting a leaf function: simple mode
+and advanced mode. Both call to Tcl. It is easy to call from Tcl to
+native code, as presented in this guide. We tap into
+<a href="http://www.swig.org">SWIG</a> which allows us to use a standard
+language-language tool to help automate this process. (SWIG
+is a nice skill to have in general, so the techniques here are usable
+outside Swift as well!)</p></div>
+<div class="paragraph"><p>The modes have separate syntax:</p></div>
+<div class="paragraph"><p><strong>Simple:</strong></p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>(int o) f(int i) "my_pkg" "version"
+[ "set <<o>> [ f <<i>> ]" ];</code></pre>
+</div></div>
+<div class="paragraph"><p>Thus, in the simple mode the user specifies the exact Tcl line to
+execute. Data dependencies are handled by Swift. Thus, that
+Tcl line runs <em>after</em> <code>i</code> has a value and <code>o</code> is a writable variable.</p></div>
+<div class="paragraph"><p>More complex Tcl programming can be done on that line. However,
+it is probably best to pack any additional logic into the Tcl
+function <code>f</code>.</p></div>
+<div class="paragraph"><p><strong>Advanced:</strong></p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>(int o) f(int i) "my_pkg" "version" "f";</code></pre>
+</div></div>
+<div class="paragraph"><p>In the advanced mode, <code>f</code> is issued <em>before</em> <code>i</code> has a value. The
+user must use the Turbine API to set up execution dependent on <code>i</code>.
+This guide will demonstrate how to do that.</p></div>
+<div class="paragraph"><p>Additionally, you may call Swift/T from native code.</p></div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_examples">2. Examples</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Complete code samples for each example are found in this tar file:</p></div>
+<div class="ulist"><ul>
+<li>
+<p>
+<a href="examples.tar.gz">examples.tar.gz</a> (12 KB)
+</p>
+</li>
+</ul></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<div class="title">Note</div>
+</td>
+<td class="content">In many scripts, we use shell options <code>set -ex</code>.</td>
+</tr></table>
+</div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<div class="title">Note</div>
+</td>
+<td class="content">You may need to modify some scripts to set the location of Tcl
+or other system tools.</td>
+</tr></table>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_simple_mode">3. Simple mode</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>Calling Tcl from Swift in simple mode is easy. However, the user
+does have to have a basic understanding of Tcl. In typical cases, the
+user will want to make a Tcl package so that multiple complex Tcl
+functions can be called, which may link to native code.</p></div>
+<div class="sect2">
+<h3 id="_complete_example_1_pure_tcl_function">3.1. Complete example 1: Pure Tcl function</h3>
+<div class="paragraph"><p>Consider the Tcl source file <code>f.tcl</code>:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>package provide my_pkg 0.1
+
+namespace eval my_pkg {
+ proc f { x y } {
+ return [ expr $x + $y ]
+ }
+}</code></pre>
+</div></div>
+<div class="paragraph"><p>This simply defines a function <code>f</code> that adds two numbers together.
+Tcl command <code>puts</code> prints the result (as <code>puts()</code> in C). Thus,
+writing a Tcl function for Swift involves:</p></div>
+<div class="olist arabic"><ol class="arabic">
+<li>
+<p>
+creating a namespace (which will be used to group functions into a package) and
+</p>
+</li>
+<li>
+<p>
+defining Tcl functions to call.
+</p>
+</li>
+</ol></div>
+<div class="paragraph"><p>It may be tested with this test (<code>test-f-1.tcl</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>source "f.tcl"
+set z [ my_pkg::f 2 3 ]
+puts $z</code></pre>
+</div></div>
+<div class="paragraph"><p>Calling this from the shell looks like this:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>$ tclsh test-f-1.tcl
+5</code></pre>
+</div></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<div class="title">Note</div>
+</td>
+<td class="content">On your system, the Tcl shell <code>tclsh</code> may be called <code>tclsh8.5</code></td>
+</tr></table>
+</div>
+<div class="paragraph"><p>Thus, to load this into Swift, we need to be able to:</p></div>
+<div class="olist arabic"><ol class="arabic">
+<li>
+<p>
+load <code>f.tcl</code> and
+</p>
+</li>
+<li>
+<p>
+invoke it.
+</p>
+</li>
+</ol></div>
+<div class="paragraph"><p>To make it easy to load <code>f.tcl</code>, we create a Tcl
+package for it. This is done with a simple Tcl line that groups
+together a package name. Conventionally this is put in
+<code>make-package.tcl</code>:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>puts [ ::pkg::create -name my_pkg -version 0.1 -source f.tcl ]</code></pre>
+</div></div>
+<div class="paragraph"><p>This simply includes the name, version, and Tcl source files to put in
+the package. Multiple <code>-source</code> arguments may be used.</p></div>
+<div class="paragraph"><p>The Tcl package is represented in a file that must be called
+<code>pkgIndex.tcl</code>. This directory containing this file is found by Tcl
+via the <code>TCLLIBPATH</code> variable. (This is similar to <code>LD_LIBRARY_PATH</code>,
+Java’s <code>CLASSPATH</code>, Python’s <code>PYTHONPATH</code>, etc.).</p></div>
+<div class="admonitionblock">
+<table><tr>
+<td class="icon">
+<div class="title">Note</div>
+</td>
+<td class="content"><code>TCLLIBPATH</code> is space-separated (which makes for easier Tcl processing).</td>
+</tr></table>
+</div>
+<div class="paragraph"><p>We create <code>pkgIndex.tcl</code> from the shell:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>$ tclsh make-package.tcl > pkgIndex.tcl</code></pre>
+</div></div>
+<div class="paragraph"><p>Now, we can test our function <code>f</code> by accessing through the package
+(instead of a simple <code>source</code> command). First the Tcl to load and run
+the package (<code>test-f-2.tcl</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>package require my_pkg 0.1
+set z [ my_pkg::f 2 3 ]
+puts $z</code></pre>
+</div></div>
+<div class="paragraph"><p>Now, invoke this test from the shell (<code>test-f-2.sh</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>$ export TCLLIBPATH=$PWD
+$ tclsh test-f-2.tcl
+5</code></pre>
+</div></div>
+<div class="paragraph"><p>The next step is to call this from Swift. First, define the typed
+Swift call to the external Tcl function <code>f</code> (<code>f.swift</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>(int o) f(int i1, int i2) "my_pkg" "0.0"
+[ "set <<o>> [ my_pkg::f <<i1>> <<i2>> ]" ];</code></pre>
+</div></div>
+<div class="paragraph"><p>Then, build a simple Swift test script to try it (<code>test-f.swift</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>import io;
+import f;
+main
+{
+ int x = 2;
+ int y = 3;
+ int z = f(x,y);
+ printf("sum: %i", z);
+}</code></pre>
+</div></div>
+<div class="paragraph"><p>Now, make the package available to Turbine and run it:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>$ stc -r $PWD test-f.swift test-f.tcl
+$ turbine test-f.tcl
+sum: 5</code></pre>
+</div></div>
+<div class="paragraph"><p><strong>Conclusion:</strong> Now you can make many concurrent calls to a simple Tcl
+function using Swift.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_complete_example_2_simple_c_function">3.2. Complete example 2: Simple C function</h3>
+<div class="paragraph"><p>This section describes how to call C functions concurrently from Swift.</p></div>
+<div class="sect3">
+<h4 id="_establish_the_c_library">3.2.1. Establish the C library</h4>
+<div class="paragraph"><p>Consider the following target C library header (<code>g.h</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>int g(int i1, int i2);</code></pre>
+</div></div>
+<div class="paragraph"><p>implemented with (<code>g.c</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>#include <stdio.h>
+
+#include "g.h"
+
+int g(int i1, int i2)
+{
+ int sum = i1+i2;
+ printf("g: %i+%i=%i\n", i1, i2, sum);
+ printf("sleeping for %i seconds...\n", sum);
+ sleep(sum);
+}</code></pre>
+</div></div>
+<div class="paragraph"><p>This function is normally called as (<code>test-g.c</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>#include "g.h"
+
+main()
+{
+ g(2, 3);
+}</code></pre>
+</div></div>
+<div class="paragraph"><p>It may be compiled and run with (<code>test-g.sh</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>#!/bin/sh
+
+gcc -c g.c || exit 1
+gcc -c test-g.c || exit 1
+gcc -o g.x test-g.o g.o || exit 1
+
+./g.x</code></pre>
+</div></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>> time ./g.x
+g: 2+3=5
+sleeping for 5 seconds...
+./g.x 0.00s user 0.00s system 0% cpu 5.003 total</code></pre>
+</div></div>
+</div>
+<div class="sect3">
+<h4 id="_export_the_c_library_as_a_tcl_package">3.2.2. Export the C library as a Tcl package</h4>
+<div class="paragraph"><p>Now, we would like to call many concurrent instances of <code>g()</code>. First,
+we need to make the Tcl package.</p></div>
+<div class="paragraph"><p>First, we run SWIG on the header:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>swig -module g g.h</code></pre>
+</div></div>
+<div class="paragraph"><p>SWIG produces <code>g_wrap.c</code>. Compile this and create a Tcl package
+(<code>test-swig-g.sh</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>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 &&
+tclsh make-package.tcl > pkgIndex.tcl</code></pre>
+</div></div>
+<div class="paragraph"><p>This produces <code>libg.so</code> and the Tcl package file <code>pkgIndex.tcl</code>.
+We test this from Tcl (<code>test-g.tcl</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>package require g 0.0
+g 2 3</code></pre>
+</div></div>
+<div class="paragraph"><p>This is run from the shell as (<code>test-g-tcl.sh</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>> export TCLLIBPATH=$PWD
+> tclsh test-g.tcl
+g: 2+3=5
+sleeping for 5 seconds...</code></pre>
+</div></div>
+</div>
+<div class="sect3">
+<h4 id="_call_the_tcl_package_from_swift_one_shot">3.2.3. Call the Tcl package from Swift (one-shot)</h4>
+<div class="paragraph"><p>Then, we bring the Tcl package into Swift (<code>test-g-1.swift</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>@dispatch=WORKER
+(int sum) g(int i1, int i2) "g" "0.0"
+[ "set <<sum>> [ g <<i1>> <<i2>> ]" ];
+
+main {
+ int sum = g(2, 3);
+}</code></pre>
+</div></div>
+<div class="paragraph"><p>Compile and run (<code>test-g-1.sh</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>> stc test-g-1.swift test-g-1.tcl
+
+# Point Turbine to the Tcl package for g
+> export TURBINE_USER_LIB=$PWD
+# Turn off logging
+> export TURBINE_LOG=0
+
+> time turbine test-g-1.tcl
+turbine test-g-1.tcl 5.60s user 0.44s system 113% cpu 5.300 total</code></pre>
+</div></div>
+</div>
+<div class="sect3">
+<h4 id="_call_the_tcl_package_from_swift_concurrently">3.2.4. Call the Tcl package from Swift concurrently</h4>
+<div class="paragraph"><p>Write a foreach loop around the call to <code>g</code> (<code>test-g-n.swift</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>@dispatch=WORKER
+(int sum) g(int i1, int i2) "g" "0.0"
+[ "set <<sum>> [ g <<i1>> <<i2>> ]" ];
+
+main {
+ foreach i in [0:5] {
+ int sum = g(i, 5-i);
+ }
+}</code></pre>
+</div></div>
+<div class="paragraph"><p>Compile and run (<code>test-g-n.swift</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>> stc test-g-n.swift test-g-n.tcl
+
+# Point Turbine to the Tcl package for g
+> export TURBINE_USER_LIB=$PWD
+# Turn off logging
+> export TURBINE_LOG=0
+
+# Single worker mode:
+> time turbine test-g-n.tcl
+g: 0+5=5
+sleeping for 5 seconds...
+g: 1+4=5
+...
+g: 5+0=5
+sleeping for 5 seconds...
+turbine test-g-n.tcl 30.60s user 2.26s system 108% cpu 30.300 total
+
+# Many worker mode:
+> time turbine -n 7 test-g-n.tcl
+...
+turbine -n 7 test-g-n.tcl 7.30s user 0.56s system 146% cpu 5.375 total</code></pre>
+</div></div>
+<div class="paragraph"><p>Thus, providing 1 worker for each loop iteration yields perfect
+speedup. Note that we had to provide 7 MPI processes: one for each of
+the 6 loop iterations and one ADLB server.</p></div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_complete_example_3_c_function_with_binary_data">3.3. Complete example 3: C function with binary data</h3>
+<div class="paragraph"><p>In this case, we pass binary data in a byte array between Swift and C.</p></div>
+<div class="paragraph"><p>The application in this case consumes a binary file containing
+double precision floats. It manipulates the data in Swift and passes
+it to a C library. The C library returns the sum of the numbers
+as an array of double precision numbers of length 1.</p></div>
+<div class="sect3">
+<h4 id="_create_the_data_set">3.3.1. Create the data set</h4>
+<div class="paragraph"><p>First, we create our binary file using the provided
+<code>turbine-write-doubles</code>/<code>turbine-read-doubles</code> tools
+(<code>create-data.sh</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>> turbine-write-doubles input.data 1 2 3 10
+
+# Check that it worked:
+> du -b input.data
+32 input.data
+> od -t f8 input.data
+0000000 1 2
+0000020 3 10
+0000040
+> turbine-read-doubles input.data
+1.0000
+2.0000
+3.0000
+10.0000</code></pre>
+</div></div>
+<div class="paragraph"><p>Simple manipulation can be performed in Swift as (<code>test-b-simple.swift</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>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]);
+}</code></pre>
+</div></div>
+<div class="paragraph"><p><code>test-b-simple.sh</code>:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>> stc test-b-simple.swift test-b-simple.tcl
+> turbine test-b-simple.tcl
+size(v) = 4
+v[last]=10.00
+v[0]=1.00</code></pre>
+</div></div>
+</div>
+<div class="sect3">
+<h4 id="_define_the_c_function">3.3.2. Define the C function</h4>
+<div class="paragraph"><p>Our C function is (<code>b.c</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>#include <stdio.h>
+#include <stdlib.h>
+
+#include "b.h"
+
+double* b(double* v, int length) {
+ int i;
+ double sum = 0.0;
+ printf("length: %i\n", length);
+ for (i = 0; i < length; i++) {
+ sum += v[i];
+ }
+ printf("sum: %f\n", sum);
+ double* result = malloc(sizeof(double));
+ result[0] = sum;
+ return result;
+}</code></pre>
+</div></div>
+<div class="paragraph"><p>It may be tested from C with (<code>test-b.c</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>#include <stdlib.h>
+#include "b.h"
+
+main() {
+ double v[4] = { 1, 2, 3, 10 };
+ double* sum = b(v, 4);
+ free(sum);
+}</code></pre>
+</div></div>
+<div class="paragraph"><p><code>test-b.sh</code>:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>> gcc -c b.c
+> gcc -c test-b.c
+> gcc -o b.x test-b.o b.o
+> ./b.x
+length: 4
+sum: 16.000000</code></pre>
+</div></div>
+</div>
+<div class="sect3">
+<h4 id="_create_the_tcl_package">3.3.3. Create the Tcl package</h4>
+<div class="paragraph"><p>Build the Tcl package with (<code>swig-b.sh</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>rm *.o
+swig -module b b.h
+gcc -c -fPIC b.c
+gcc -c -fPIC -I /usr/include/tcl8.5 b_wrap.c
+gcc -shared -o libb.so b_wrap.o b.o
+tclsh make-package.tcl > pkgIndex.tcl</code></pre>
+</div></div>
+<div class="paragraph"><p>Since the blob pointer is of type <code>void*</code>, we need to wrap the C
+function in some helper Tcl code to transmit blob data to the typed C
+function. This is performed in <code>b.tcl</code>:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>namespace eval b {
+ # v is formatted as a Turbine blob a list of [ pointer length ]
+ # The pointer is a simple Tcl integer
+ # The length is the byte length
+ proc b_tcl { v } {
+
+ # Unpack the list
+ set ptr [ lindex $v 0 ]
+ set len [ lindex $v 1 ]
+
+ # Get the number of numbers to sum
+ set count [ expr $len / [ blobutils_sizeof_float ] ]
+
+ # Convert the pointer number to a SWIG pointer
+ set ptr [ blobutils_cast_int_to_dbl_ptr $ptr ]
+
+ # Call the C function
+ set s [ b $ptr $count ]
+
+ # Pack result as a Turbine blob and return it
+ set r [ blobutils_cast_to_int $s ]
+ return [ list $r 8 ]
+ }
+}</code></pre>
+</div></div>
+<div class="paragraph"><p>Thus, Swift calls the Tcl wrapper, which calls the C function.
+Additional documentation for writing Tcl wrappers that use the Turbine API
+may be found in the <a href="internals.html">Turbine Internals Guide</a>;
+the <code>blobutils</code> tools are described in the
+<a href="internals.html#_blob_manipulation">blobs section</a>.</p></div>
+<div class="paragraph"><p>Note that we return blob containing a pointer to freshly allocated
+memory to Swift. The system will release this memory.</p></div>
+</div>
+<div class="sect3">
+<h4 id="_call_from_swift">3.3.4. Call from Swift</h4>
+<div class="paragraph"><p>The Swift code to pass the blob to <code>b()</code> is as follows
+(<code>test-b.swift</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>import blob;
+import io;
+
+(blob sum) b(blob v) "b" "0.0"
+[ "set <<sum>> [ b::b_tcl <<v>> ]" ];
+
+main {
+ file data = input_file("input.data");
+ blob v = blob_read(data);
+ blob s = b(v);
+ float sum[] = floats_from_blob(s);
+ printf("sum (swift): %f", sum[0]);
+}</code></pre>
+</div></div>
+<div class="paragraph"><p><code>test-b-swift.sh</code>:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>> stc test-b.swift test-b.tcl
+> turbine test-b.tcl
+length: 4
+sum: 16.000000
+sum (swift): 16.000000</code></pre>
+</div></div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_complete_example_4_calling_a_fortran_function">3.4. Complete example 4: Calling a Fortran function</h3>
+<div class="paragraph"><p>In this example, we call Fortran from Swift. We do this by wrapping
+the Fortran function in a C++ wrapper by using
+<a href="http://fortwrap.sourceforge.net">FortWrap</a>. Then, we wrap for Swift by
+using SWIG.</p></div>
+<div class="paragraph"><p>This example will demonstrate multiplying <code>y=A*x</code> using Swift to call
+a user Fortran library, which in turn calls the BLAS function
+<code>dgemv</code>. This demonstrates the generality of our model.</p></div>
+<div class="imageblock latex">
+<div class="content">
+<img src="leaf__1.png" alt="leaf__1.png" />
+</div>
+</div>
+<div class="sect3">
+<h4 id="_establish_the_fortran_function">3.4.1. Establish the Fortran function</h4>
+<div class="paragraph"><p>Consider the Fortran function (<code>mvm.f</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>! Matrix-Vector Multiply: y = A*x via BLAS
+ subroutine MVM(A, x, y, n)
+
+ integer, intent(IN) :: n
+ double precision, intent(IN) :: A(n,n)
+ double precision, intent(IN) :: x(n)
+ double precision, intent(OUT) :: y(n)
+
+ double precision :: alpha, beta
+
+ alpha = 1.0D0
+ beta = 0.0D0
+ call dgemv('N', n, n, alpha, A, n, x, 1, beta, y, 1)
+
+ end subroutine</code></pre>
+</div></div>
+<div class="paragraph"><p>A test program to run this is (<code>test-mvm.f</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code> program testMVM
+
+ parameter (n = 2)
+ double precision :: A(n,n)
+ double precision :: x(n)
+ double precision :: y(n)
+ double precision :: alpha, beta
+
+ open (unit=1, file='A.data', form='unformatted',
+ $ access='direct', recl=n*n*8)
+ read (1, rec=1) A
+ close (1)
+
+ open (unit=1, file='x.data', form='unformatted',
+ $ access='direct', recl=n*8)
+ read (1, rec=1) x
+ close (1)
+
+ do i = 1,n
+ y(i) = 0.0D0
+ end do
+
+ call MVM(A, x, y, n)
+
+ print *, "y"
+ print *, y(1)
+ print *, y(2)
+
+ end program</code></pre>
+</div></div>
+<div class="paragraph"><p>It is built and run with (<code>test-mvm.sh</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>#!/bin/bash
+
+# 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
+
+./test-MVM.x</code></pre>
+</div></div>
+<div class="paragraph"><p>FortWrap will scan <code>mvm.f</code> and produce the C++ files <code>FortFuncs.h</code> and
+<code>FortFuncs.cpp</code>, which we wrap with SWIG to produce a Tcl function
+called <code>FortFuncs_MVM</code>. We can call this from Swift.</p></div>
+</div>
+<div class="sect3">
+<h4 id="_write_the_swift_code_and_tcl_wrapper">3.4.2. Write the Swift code and Tcl wrapper</h4>
+<div class="paragraph"><p>Our goal is to rewrite <code>test-mvm.f</code> in Swift so we can call <code>MVM</code>
+concurrently on many processors. Our Swift replacement is
+(<code>test-mvm.swift</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>import blob;
+import io;
+
+(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);
+ }
+}</code></pre>
+</div></div>
+<div class="paragraph"><p>Our Tcl wrapper converts the Tcl call to <code>mvm</code> on blob arguments
+to the Tcl call to <code>FortFuncs_MVM</code> on pointers. This is performed
+similarly to the C example above (<code>mvm.tcl</code>).</p></div>
+</div>
+<div class="sect3">
+<h4 id="_build_and_run">3.4.3. Build and run</h4>
+<div class="paragraph"><p>Now, we build everything (<code>build.sh</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>#!/bin/bash -e
+
+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
+swig -c++ -module mvm FortFuncs.h
+# Minor fix to the wrapper code
+sed -i '11i#include "FortFuncs.h"' FortFuncs_wrap.cxx
+
+# Compile everything
+g++ -c -fPIC -I . FortFuncs.cpp
+g++ -c -fPIC -I ${TCL_INCLUDE} FortFuncs_wrap.cxx
+gfortran -c -fPIC mvm.f
+
+# Build the shared object
+g++ -shared -o libmvm.so FortFuncs_wrap.o FortFuncs.o mvm.o ${BLAS} -lgfortran
+
+# Make the Tcl package
+${TCLSH} make-package.tcl > pkgIndex.tcl</code></pre>
+</div></div>
+<div class="paragraph"><p>We run it in Swift with (<code>test-mvm-swift.sh</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>#!/bin/bash
+
+stc test-mvm.swift test-mvm.tcl
+
+export TURBINE_USER_LIB=$PWD
+turbine test-mvm.tcl</code></pre>
+</div></div>
+<div class="paragraph"><p>This produces:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>y[0]=17.000000
+y[1]=39.000000</code></pre>
+</div></div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_complete_example_5_calling_c_with_code_argc_argv_code">3.5. Complete example 5: Calling C with <code>argc/argv</code></h3>
+<div class="paragraph"><p>It may be desirable to call an existing C <em>program</em> from Swift
+with as little modification as possible. This example considers the
+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 <code>main()</code> function and calling that from Swift/T.</p></div>
+<div class="paragraph"><p>Consider the user code (<code>swift-main.c</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>#include <stdio.h>
+#include "swift-main.h"
+int swift_main(int argc, char* argv[]) {
+ for (int i = 0; i < argc; i++)
+ printf("arg[%i]: %s\n", i, argv[i]);
+ return 0;
+}</code></pre>
+</div></div>
+<div class="paragraph"><p>This is essentially a simple C program except that its <code>main()</code> function
+has been renamed to <code>swift_main()</code>. Also, the header <code>swift-main.h</code>
+has been created to allow the Swift/T framework to call this code.
+The function essentially acts like <code>/bin/echo</code>, reporting its
+arguments.</p></div>
+<div class="paragraph"><p>An example C wrapper to call this function is as follows (<code>prog-c.c</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>#include "swift-main.h"
+int main(int argc, char* argv[]) {
+ swift_main(argc, argv);
+ return 0;
+}</code></pre>
+</div></div>
+<div class="paragraph"><p>The equivalent Swift code is as follows (<code>prog-swift.swift</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>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);
+}</code></pre>
+</div></div>
+<div class="paragraph"><p>The Swift version defines the extension function symbol <code>swift_main</code>,
+then calls it with the given array of strings. The "exit code"
+(actually just a return value) is available to Swift.</p></div>
+<div class="paragraph"><p>This example may be compiled and run (from C, Tcl, and Swift) by using
+the provided Makefile.</p></div>
+<div class="paragraph"><p>The above process is semi-automated by the <code>genleaf</code> 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 <code>turbine</code>. Invoke <code>genleaf</code> as follows:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>./genleaf ex2.c ex2.h
+turbine user-code.tcl</code></pre>
+</div></div>
+</div>
+<div class="sect2">
+<h3 id="_complete_example_6_calling_fortran_with_code_argc_argv_code">3.6. Complete example 6: Calling Fortran with <code>argc/argv</code></h3>
+<div class="paragraph"><p>It may be desirable to call an existing Fortran <em>program</em> from Swift
+with as little modification as possible. This example considers the
+case that the Swift program will construct an array of strings to pass
+to the Fortran code. The Fortran program is minimally modified by
+removing its "open code" and exposing a function that accepts an array
+of strings instead of using Fortran builtins
+<code>command_argument_count()</code> and <code>get_command_argument()</code>.</p></div>
+<div class="paragraph"><p>Consider the Fortran function <code>func()</code> (<code>func.f90</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code> subroutine func(argc, argv, output)
+
+ implicit none
+
+ integer, intent(in) :: argc
+ type (string_array) :: argv
+ double precision, intent(out) :: output</code></pre>
+</div></div>
+<div class="paragraph"><p>The <code>argc/argv</code> is stored in a <code>string_array</code>, defined in the top of
+<code>func.f90</code>.</p></div>
+<div class="paragraph"><p>This data structure is constructed and filled by the program
+<code>prog-f90.f90</code> as follows:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>argc = command_argument_count()
+call string_array_create(argv, argc)
+
+do i = 1, argc
+ call get_command_argument(i, tmp)
+ call string_array_set(argv, i, tmp)
+end do</code></pre>
+</div></div>
+<div class="paragraph"><p>To call this function from Swift, follow the <code>Makefile</code>. (You may
+need to set the Tcl directory.)</p></div>
+<div class="olist arabic"><ol class="arabic">
+<li>
+<p>
+We first wrap the Fortran with FortWrap to produce C++ wrappers.
+Note that FortWrap wraps the Fortran type <code>string_array</code> with a C++
+class (an example of how to use the class directly from C++ is
+provided in <code>prog-cxx.cxx</code>).
+</p>
+</li>
+<li>
+<p>
+We wrap the generated C++ header (<code>FortWrap.h</code>) with SWIG.
+</p>
+</li>
+<li>
+<p>
+We compile everything.
+</p>
+</li>
+<li>
+<p>
+A Tcl function (<code>func.tcl</code>) is used to retrieve the string array
+from Swift and create an output buffer for the output double.
+</p>
+</li>
+<li>
+<p>
+We call the function from Swift using the simple syntax:
+</p>
+<div class="listingblock">
+<div class="content">
+<pre><code>(float v) func(string A[]) "f" "0.0"
+[
+ "set <<v>> [ func <<A>> ]"
+];</code></pre>
+</div></div>
+</li>
+<li>
+<p>
+We run with:
+</p>
+<div class="listingblock">
+<div class="content">
+<pre><code>export TURBINE_USER_LIB=$PWD
+turbine prog-swift.tcl</code></pre>
+</div></div>
+</li>
+</ol></div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_advanced_mode">4. Advanced mode</h2>
+<div class="sectionbody">
+<div class="paragraph"><p>In this mode, the user provides the Swift/T runtime with dataflow
+information so that more complex operations may be performed.</p></div>
+<div class="sect2">
+<h3 id="_complete_example_7_leaf_task_with_dataflow">4.1. Complete example 7: Leaf task with dataflow</h3>
+<div class="paragraph"><p>When using the advanced syntax, the final argument is the name of a
+Tcl function:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>(int o) f(int i) "my_pkg" "version" "f";</code></pre>
+</div></div>
+<div class="paragraph"><p>This function is called <em>before</em> <code>i</code> is set. Thus, <code>f</code> must issue a
+Turbine <code>rule</code> statement to schedule real leaf work when <code>i</code> is set.</p></div>
+<div class="paragraph"><p>Consider the following Tcl code (<code>f.tcl</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>package provide my_pkg 0.0
+
+namespace eval my_pkg {
+
+ # Function called by Swift/T
+ proc f { outputs inputs } {
+ set x [ lindex $inputs 0 ]
+ set y [ lindex $inputs 1 ]
+ set z [ lindex $outputs 0 ]
+ rule [ list $x $y ] "my_pkg::f_body $z $x $y" \
+ type $turbine::WORK
+ }
+
+ # Function called by Swift/T rule
+ proc f_body { z x y } {
+ set x_value [ retrieve_integer $x ]
+ set y_value [ retrieve_integer $y ]
+ set z_value [ f_impl $x_value $y_value ]
+ store_integer $z $z_value
+ }
+
+ # Real Tcl implementation: does actual work
+ proc f_impl { x_value y_value } {
+ return [ expr $x_value + $y_value ]
+ }
+}</code></pre>
+</div></div>
+<div class="paragraph"><p>In this case, Tcl function <code>f_impl</code> is the <em>implementation</em>: the
+actual code the user desires to call. This may be an existing Tcl
+routine or linkage to native code as described above. It consumes two
+Tcl integers and returns their sum as a Tcl integer.</p></div>
+<div class="paragraph"><p>Two function, <code>f</code> and <code>f_body</code>, are required to connect this to
+Swift/T. <code>f</code> is the <em>interface</em>: it is called by Swift/T when the
+call is issued but <code>x</code> and <code>y</code> may not yet have values. The Tcl
+variables <code>x</code> and <code>y</code> are the Turbine Datum (TD) identifiers, not the
+values, of Swift variables <code>x</code> and <code>y</code>. The outputs are packed in Tcl
+list <code>outputs</code> and the inputs are in Tcl list <code>inputs</code>.</p></div>
+<div class="paragraph"><p>When <code>x</code> and <code>y</code> are stored elsewhere, the Swift/T runtime evaluates the
+action item in the rule: <code>"my_pkg::f_body $z $x $y"</code>. Thus, <code>f_body</code>
+receives the TDs for <code>z</code>, <code>x</code>, and <code>y</code>. It retrieves the values of
+<code>x</code> and <code>y</code>, calls <code>f_impl</code> to compute the value for <code>z</code>, and stores
+it. Now, any Swift/T statements (rules) dependendent on <code>z</code> will be
+executed, and so on.</p></div>
+<div class="paragraph"><p>This Tcl code is called by the following simple Swift/T test
+(<code>test-f.swift</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>import io;
+
+(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);
+}</code></pre>
+</div></div>
+<div class="paragraph"><p>For more information about the APIs used to store/retrieve Swift/T
+data and issue rules, see <a href="turbine-internals.html">Turbine
+Internals</a>.</p></div>
+<div class="paragraph"><p>The interface/body/implementation pattern is used by much of the
+Swift/T library. The source of this library is found in the Turbine
+installation directory. The Swift headers are in <code>turbine/export</code> and
+their Tcl implementations are in <code>turbine/lib</code>. This is a good way to
+find out what else may be done.</p></div>
+</div>
+<div class="sect2">
+<h3 id="_complete_example_8_calling_an_mpi_library">4.2. Complete example 8: Calling an MPI library</h3>
+<div class="paragraph"><p>Calling an existing MPI library is similar to calling any other C
+code. In this example, we will show how to obtain the new
+communicator from Swift/T. This functionality only works when using
+Swift/T on an MPI-3 implementation such as MPICH 3.0.</p></div>
+<div class="sect3">
+<h4 id="_identify_the_function">4.2.1. Identify the function</h4>
+<div class="paragraph"><p>Consider the following MPI library function (<code>f.c</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>double
+f(MPI_Comm comm, int k)
+{
+ int task_rank, task_size;
+ MPI_Comm_rank(comm, &task_rank);
+ MPI_Comm_size(comm, &task_size);
+ MPI_Barrier(comm);
+ sleep(task_rank);
+ MPI_Barrier(comm);
+ if (task_rank == 0)
+ // Return a real value
+ return sin(k+task_size);
+ // Return a placeholder
+ return 0.0;
+}</code></pre>
+</div></div>
+<div class="paragraph"><p>This function accepts an MPI communicator <code>comm</code> freshly created for
+the task. It also accepts user data <code>k</code> and must return a <code>double</code>.
+Rank 0 in the task communicator returns the real value- the other
+ranks may cooperate in the computation but do not interact with the
+data store.</p></div>
+<div class="paragraph"><p>Communication on <code>comm</code> is isolated from Swift/T implementation
+communication. Point-to-point messaging and collectives (such as
+<code>MPI_Barrier()</code>, as shown) are allowed.</p></div>
+<div class="paragraph"><p>We desire to call this from Swift as (<code>test-f.swift</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>import io;
+
+ at 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);
+}</code></pre>
+</div></div>
+<div class="paragraph"><p>In the declaration, <code>@par</code> allows us to call the function as a
+parallel function. At call time, we use <code>@par=2</code>.</p></div>
+<div class="paragraph"><p>We wrap this function with SWIG and a Swift/T interface/body:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>namespace eval f {
+
+ proc f_tcl { outputs inputs args } {
+ set z [ lindex $outputs 0 ]
+ set k [ lindex $inputs 0 ]
+ rule $k "f::f_tcl_body $z $k" {*}$args type $turbine::WORK
+ }
+
+ proc f_tcl_body { z k } {
+ # Retrieve k
+ set k_value [ retrieve_integer $k ]
+ # Look up MPI information
+ set comm [ turbine::c::task_comm ]
+ set rank [ turbine::c::task_rank ]
+ # Run the user code
+ set z_value [ f $comm $k_value ]
+ # Store result
+ if { $rank == 0 } {
+ store_float $z $z_value
+ }
+ }
+}</code></pre>
+</div></div>
+<div class="paragraph"><p>This differs from the single-process task (example 5) in that it
+passes the additional parallelism information in variable <code>args</code> into
+the <code>rule</code> statement so that Swift/T will allocate 2 workers for the
+task.</p></div>
+<div class="paragraph"><p>By convention, only rank 0 contacts the data store to store result
+<code>z</code>. If multiple processes write to <code>z</code>, a run-time error will
+result.</p></div>
+<div class="paragraph"><p>At run time, ensure Turbine has enough workers to run the user task:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>> turbine -n 4 test-f.tcl
+z: -0.959</code></pre>
+</div></div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_calling_swift_t_from_native_code">5. Calling Swift/T from native code</h2>
+<div class="sectionbody">
+<div class="sect2">
+<h3 id="_complete_example_9_calling_swift_t_from_c">5.1. Complete example 9: Calling Swift/T from C</h3>
+<div class="paragraph"><p>Swift/T itself may be called from native code as a library.</p></div>
+<div class="sect3">
+<h4 id="_compilation">5.1.1. Compilation</h4>
+<div class="paragraph"><p>The Turbine installation directory contains the <code>turbine.h</code> header and
+the <code>libtclturbine.so</code> shared object. See <code>build.sh</code> for the example
+compiler commands.</p></div>
+</div>
+<div class="sect3">
+<h4 id="_call">5.1.2. Call</h4>
+<div class="paragraph"><p>The call to Swift/T requires the MPI communicator in which to run, the
+compiled Swift/T program to run, a C-formatted <code>argc</code>/<code>argv</code>, and an
+output pointer.</p></div>
+<div class="paragraph"><p>The C call to Swift/T is written as (<code>controller.c</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>turbine_code rc = turbine_run(comm, "test-f.tcl", argc, argv, output);</code></pre>
+</div></div>
+<div class="paragraph"><p>where <code>argc</code>/<code>argv</code> are C-style arguments, and <code>output</code> is the buffer
+to hold the output.</p></div>
+<div class="paragraph"><p>The Swift script is a normal Swift script except for the call to
+<code>turbine_run_output_blob()</code>, which returns data to the controller
+(<code>test-f.swift</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>import blob;
+import io;
+import sys;
+
+main
+{
+ printf("args: %s", args());
+ string s = "MY_OUTPUT";
+ blob b = blob_from_string(s);
+ turbine_run_output_blob(b);
+}</code></pre>
+</div></div>
+<div class="paragraph"><p>The controller MPI program is run as: (<code>run.sh</code>):</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>#!/bin/sh -e
+
+./build.sh
+
+mpiexec -n 4 ./controller.x</code></pre>
+</div></div>
+<div class="paragraph"><p>producing:</p></div>
+<div class="listingblock">
+<div class="content">
+<pre><code>args: howdy ok bye
+controller: output: MY_OUTPUT</code></pre>
+</div></div>
+<div class="paragraph"><p>Note that only rank 0 in the Swift/T communicator has access to the
+<code>output</code> data.</p></div>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div id="footnotes"><hr /></div>
+<div id="footer">
+<div id="footer-text">
+Last updated 2014-07-18 15:56:48 CDT
+</div>
+</div>
+</body>
+</html>
More information about the Swift-commit
mailing list