Installing TensorFlow on an AWS EC2 P2 GPU Instance

Amazon just recently released new AWS EC2 P2 instance types featuring K80 GPUs. In this blog post I’ll cover how to configure and install TensorFlow on a Ubuntu 16.04 targeting these new GPU instance types. This article is building upon previous blog post by John Ramey on installing TensorFlow for older AWS GPU instance types.

The following components will be installed:

  • Essentials
  • CUDA 8.0
  • Download cuDNN v5.1 (August 10, 2016), for CUDA 8.0
  • Bazel 0.3.2 (Java 8 is a dependency)
  • TensorFlow 0.11

This tutorial was written for a p2.xlarge instance type, however all AWS P2 instance types should work. You’re going to need 16 GiB of storage on the root partition to follow this guide.


Synchronous Functional Dataflow Programming & Closures of Named Functions

When I originally selected the name for this blog back many years ago, I had the topic of this post in mind. For me, dataflow programming has always resembled functional programming and many concepts natural in functional programming translate very well into dataflow world. The key concept in functional programming is the idea that any expression can be passed around as a value within the application. Translating this idea into dataflow programming would mean that one could pass around subdiagrams in your dataflow diagram.

Passing around function references is nothing new to dataflow programming. For example LabVIEW has supported references to named functions for a long time. However, passing around references to named functions isn’t very interesting as the expressivity of named functions doesn’t adapt to the context.

To take advantage of the full power of functional programming the concept of closures needs to be introduced to the dataflow programming. A closure is a function definition or reference together with an environment that defines some of the input values to the function. When passing around functions in a functional programming, one actually passes around closures i.e. functions with their partially predetermined environment.

Let’s look how this concept would adapt to synchronous dataflow programming languages such as LabVIEW.  In the image below we illustrate the construction of a closure of a named function “add”.

Constructing a closure in functional synchronous dataflow programming, passing it around as a value and calling it using an apply method

Constructing a closure in functional synchronous dataflow programming, passing it around as a value and calling it using an apply method

We introduce a new closure structure (on the left) that constructs a closure of a function inside the structure. The environment of the closure if determined by connecting wires from outside the diagram to one or more of the input terminals of the function within the closure structure. In the example above we have constructed a closure of an “add” function by fixing it’s first input to constant value of 3. Naturally the value didn’t have to be constant, it could as well be any value flowing in the wire. The output of the closure structure returns an expression representing a function definition of f: f(x)=x+3.

The closure can be called by passing the closure to an apply structure (on the right). The apply structure is a function that is expecting a function definition as an input. It allows the programmer to bind the unbound terminals of the function. Execution of the apply structure leads into evaluation of the function determined by the function input terminal (green terminal) by binding the unbound terminals to defined values at the time of execution of the apply structure and then evaluating the function.

In the above example, a closure representing a partial function is first constructed by binding number three to one of the terminals of the add function and then passing this closure forward to an apply structure. The apply structure then binds the other terminal to value seven and evaluates the function. The result of the evaluation is 3+7 = 10.

Using closure in the above is not very useful and the example is provided for illustrative purposes. We will in the future posts discuss more the design patterns of using functional synchronous dataflow programming. We will also introduce closures of anonymous functions defined in-place on the diagram. The principles introduced here can be extended into flow-based programming paradigm and I will discuss this in a future post.

Happy Thanksgiving!



Thanksgiving Flow Diagram


Happy Thanksgiving 2013 for all the ExpressionFlow readers.  Enjoy the flow of fresh harvest with the friends and family!

Embedding synchronous dataflow into a flow-based programming diagram

In my previous post I discussed about combining flow-based programming and syncrhonous dataflow both in a single visual programming language. The goal of such language would be to combine the best of  both of the flow-based approaches allowing the developer to choose the paradigm that best suits to the problem in hand. Today I want to take a deeper look into this hybrid dataflow model and introduce a specific synchronous structure that, from outside the structure appears and acts like a normal asynchronous flow-based programming node but from within encloses a synchronous dataflow diagram.

Consider an image processing task of smoothing an image by replacing each pixel value with an average of rectangular 3×3 neighborhood of the original pixel. We want to implement such an algorithm in our hybrid flow-based programming application. The input and output of such diagram needs to be a stream of images. Perhaps we have a flow-based programming diagram where we read images from a folder, pass them to the smoothing algorithm that then passes them to a node saving them back to the disk.

A Flow-Based Programming application that iterates over all of the images in a folder and smooths them using a Smooth Image subdiagram.

A Flow-Based Programming application that iterates over all of the images in a folder and smooths them using a Smooth Image subdiagram.

Now let’s take a look at the implementation of the Smooth Image subdiagram in the above flow-based programming example. The Smooth Image subdiagram is illustrated in the image below that takes advantage of the proposed new  synchronous structure. The synchronous structure in the subdiagram processes a stream of images, each of which is represented by a single information package (or an object in a OOP flavored language). The images arrive in an asynchronous manner from the previous Read Image step. In the examples, the asynchronous wires are represented with dotted lines and the synchronous wire with solid lines.

Embedding synchronous dataflow diagram into a flow-based programming diagram using a specific synchronous structure

Embedding synchronous dataflow diagram into a flow-based programming diagram using a specific synchronous structure

The synchronous structure starts executing upon startup of the subdiagram and remains executing until the input image stream is closed. The diagram waits for any incoming images (information packages) in the image stream. Each image in the example is expected to be a two dimensional array containing numeric values representing gray values for each pixel.

Every time an image arrives at the left connector of the synchronous structure, the content of the synchronous structure is executed exactly once in a synchronous dataflow manner. At the start of each execution of the content the synchronous structure, the left hand side image stream input gets the value of the received grayscale image. The image is then iterated with two for loop structures, outer for loop structure iterating each row in the image and inner for loop iterating each column in the image. Within the inner for loop, a 3×3 subarea around each pixel is averaged and the averaged value for each pixel is returned. The right hand edges of the for loops reconstruct the averaged pixels into the form of the original image and the smoothed image is passed to the right edge of the synchronous structure. The synchronous structure returns the image via its left hand side connector to the asynchronous surrounding diagram when its content has completed executing.

This hybrid dataflow approach using the synchronous structure allows easily enhancing the flow-based programming with synchronous dataflow subdiagrams. This greatly enhances the expressive power of the visual dataflow and flow-based programming languages by making them well equipped for both the complicated low-level operations requiring synchronization and high level orchestration well expressed with flow-based programming diagrams.