Skip to content

Commit

Permalink
Upgrading to TensorFlow v1.2.1
Browse files Browse the repository at this point in the history
**NOTE** DeviceList is still not available in binary, the function body
is a placeholder right now and will be activate in the future version.
  • Loading branch information
RockfordWei committed Jul 18, 2017
1 parent 5317f60 commit 4944c8a
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 27 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Ensure you have installed and activated the latest Swift 3.1 tool chain; The sou

## Project Status

The framework is Beta testing now.
The framework is Beta testing now.

## Development Notes

Expand Down Expand Up @@ -80,7 +80,7 @@ API programming topics can be found in [Perfect TensorFlow Guide](GUIDE.md)
### TensorFlow C API Library Installation

Perfect-TensorFlow is based on TensorFlow C API, i.e., `libtensorflow.so` on runtime.
This project contains an express CPU v1.2.0 installation script for this module on both macOS / Ubuntu Linux, and will install the dynamic library into path `/usr/local/lib/libtensorflow.so`. You can download & run [`install.sh`](https://github.com/PerfectlySoft/Perfect-TensorFlow/blob/master/install.sh). Before running this script, please make sure that `wget` has been installed onto your computer, otherwise please run either `brew install wget` for macOS or `sudo apt-get install wget` for Ubuntu first.
This project contains an express CPU v1.2.1 installation script for this module on both macOS / Ubuntu Linux, and will install the dynamic library into path `/usr/local/lib/libtensorflow.so`. You can download & run [`install.sh`](https://github.com/PerfectlySoft/Perfect-TensorFlow/blob/master/install.sh). Before running this script, please make sure that `wget` has been installed onto your computer, otherwise please run either `brew install wget` for macOS or `sudo apt-get install wget` for Ubuntu first.

For more installation options, such as GPU/CPU and multiple versions on the same machine, please check TensorFlow website: [Installing TensorFlow for C](https://www.tensorflow.org/install/install_c)

Expand All @@ -101,7 +101,7 @@ import TensorFlowAPI
// This is the Swift version of TensorFlow classes and objects
import PerfectTensorFlow

// To keep the naming consistency with TensorFlow in other languages such as
// To keep the naming consistency with TensorFlow in other languages such as
// Python or Java, making an alias of `TensorFlow` Class is a good idea:
public typealias TF = TensorFlow
```
Expand All @@ -111,7 +111,7 @@ public typealias TF = TensorFlow
⚠️NOTE⚠️ Prior to use **ANY ACTUAL FUNCTIONS** of Perfect TensorFlow framework, `TF.Open()` must be called first:

``` swift
// this action will load all api functions defined
// this action will load all api functions defined
// in /usr/local/lib/libtensorflow.so
try TF.Open()
```
Expand Down
2 changes: 1 addition & 1 deletion README.zh_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ Sources

Perfect-TensorFlow 是基于其C语言函数库基础上的,简单说来就是您的计算机上在运行时必须安装 `libtensorflow.so`动态链接库。

本项目包含了一个用于快速安装该链接库 CPU v1.2.0版本的脚本,默认安装路径为`/usr/local/lib/libtensorflow.so`。您可以根据平台要求下载并运行 [`install.sh`](https://github.com/PerfectlySoft/Perfect-TensorFlow/blob/master/install.sh)。运行该脚本之前请确定 `wget`已经安装到您的计算机上;如果还没装,请首先用`brew install wget`(适用于macOS)或者 `sudo apt-get install wget` (适用于Ubuntu)命令安装`wget`组件。
本项目包含了一个用于快速安装该链接库 CPU v1.2.1版本的脚本,默认安装路径为`/usr/local/lib/libtensorflow.so`。您可以根据平台要求下载并运行 [`install.sh`](https://github.com/PerfectlySoft/Perfect-TensorFlow/blob/master/install.sh)。运行该脚本之前请确定 `wget`已经安装到您的计算机上;如果还没装,请首先用`brew install wget`(适用于macOS)或者 `sudo apt-get install wget` (适用于Ubuntu)命令安装`wget`组件。


更多的安装选项,如需要在同一台计算机上同时安装CPU/GPU或者多个不同版本,请参考官网网站: [Installing TensorFlow for C](https://www.tensorflow.org/install/install_c)
Expand Down
44 changes: 43 additions & 1 deletion Sources/PerfectTensorFlow/APILoader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,42 @@ public class TFLib {
/// On failure, output_values[] contains NULLs.
public static var SessionRun: @convention(c) (OpaquePointer, UnsafePointer<TF_Buffer>?, UnsafePointer<TF_Output>?, UnsafePointer<OpaquePointer>?, Int32, UnsafePointer<TF_Output>?, UnsafeMutablePointer<OpaquePointer>?, Int32, UnsafePointer<OpaquePointer>?, Int32, UnsafeMutablePointer<TF_Buffer>?, OpaquePointer) -> Void = { _, _, _, _, _, _, _, _, _, _, _, _ in }

/// Lists all devices in a TF_Session.
///
/// Caller takes ownership of the returned TF_DeviceList* which must eventually
/// be freed with a call to TF_DeleteDeviceList.
public static var SessionListDevices: @convention(c) (OpaquePointer, OpaquePointer) -> OpaquePointer? = { _, _ in return nil }

/// Deallocates the device list.
public static var DeleteDeviceList: @convention(c) (OpaquePointer) -> Void = { _ in}

/// Counts the number of elements in the device list.
public static var DeviceListCount: @convention(c) (OpaquePointer) -> Int32 = { _ in return 0 }

/// Retrieves the full name of the device (e.g. /job:worker/replica:0/...)
/// The return value will be a pointer to a null terminated string. The caller
/// must not modify or delete the string. It will be deallocated upon a call to
/// TF_DeleteDeviceList.
///
/// If index is out of bounds, an error code will be set in the status object,
/// and a null pointer will be returned.
public static var DeviceListName: @convention(c) (OpaquePointer, Int32, OpaquePointer) -> UnsafePointer<CChar>? = { _, _, _ in return nil }

/// Retrieves the type of the device at the given index.
///
/// The caller must not modify or delete the string. It will be deallocated upon
/// a call to TF_DeleteDeviceList.
///
/// If index is out of bounds, an error code will be set in the status object,
/// and a null pointer will be returned.
public static var DeviceListType: @convention(c) (OpaquePointer, Int32, OpaquePointer) -> UnsafePointer<CChar>? = { _, _, _ in return nil }

/// Retrieve the amount of memory associated with a given device.
///
/// If index is out of bounds, an error code will be set in the status object,
/// and -1 will be returned.
public static var DeviceListMemoryBytes: @convention(c) (OpaquePointer, Int32, OpaquePointer) -> Int64 = { _, _, _ in return 0 }

/// Set up the graph with the intended feeds (inputs) and fetches (outputs) for a
/// sequence of partial run calls.
///
Expand Down Expand Up @@ -758,7 +794,13 @@ public class TFLib {
throw Panic.DLL(reason: String(cString: dlerror()))
}//end lib
libDLL = lib
// AddGradients = try LoadFunction(lib, "TF_AddGradients")
// SessionListDevices = try LoadFunction(lib, "TF_SessionListDevices")
// DeleteDeviceList = try LoadFunction(lib, "TF_DeleteDeviceList")
// DeviceListCount = try LoadFunction(lib, "TF_DeviceListCount")
// DeviceListName = try LoadFunction(lib, "TF_DeviceListName")
// DeviceListType = try LoadFunction(lib, "TF_DeviceListType")
// DeviceListMemoryBytes = try LoadFunction(lib, "TF_DeviceListMemoryBytes")
AddGradients = try LoadFunction(lib, "TF_AddGradients")
SetAttrValueProto = try LoadFunction(lib, "TF_SetAttrValueProto")
GetAllOpList = try LoadFunction(lib, "TF_GetAllOpList")
DeleteLibraryHandle = try LoadFunction(lib, "TF_DeleteLibraryHandle")
Expand Down
27 changes: 27 additions & 0 deletions Sources/PerfectTensorFlow/PerfectTensorFlow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1930,6 +1930,33 @@ public class TensorFlow {

let session: OpaquePointer

/// return all devices for this session in a dictionary.
/// each key in the dictionary represents a device name,
/// and the value is a tuple of device type and its memory size, in bytes
public var devices: [String:(`type`:String, memory: Int64)] {
var dev: [String:(`type`:String, memory: Int64)] = [:]

guard let _ = TFLib.libDLL, let status = try? Status(),
let list = TFLib.SessionListDevices(session, status.status),
status.code == .OK else { return dev }

defer { TFLib.DeleteDeviceList(list) }
for i in 0 ..< TFLib.DeviceListCount(list) {
if let nm = TFLib.DeviceListName(list, i, status.status),
status.code == .OK,
let tp = TFLib.DeviceListType(list, i, status.status),
status.code == .OK {
let mem = TFLib.DeviceListMemoryBytes(list, i, status.status)
if status.code == .OK,
let dname = String(utf8String: nm),
let dtype = String(utf8String: tp) {
dev[dname] = (type: dtype, memory: mem)
}
}
}
return dev
}

/// Return a new execution session with the associated graph, or NULL on error. *graph must be a valid graph (not deleted or nullptr). This function will prevent the graph from being deleted until TF_DeleteSession() is called. Does not take ownership of opts.
/// - parameters:
/// - graph: the parent graph
Expand Down
1 change: 1 addition & 0 deletions Sources/TensorFlowAPI/include/TensorFlowAPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ typedef struct TF_WhileParams {
// API for driving Graph execution.

typedef struct TF_Session TF_Session;
typedef struct TF_DeviceList TF_DeviceList;

// Load plugins containing custom ops and kernels

Expand Down
43 changes: 25 additions & 18 deletions Tests/PerfectTensorFlowTests/PerfectTensorFlowTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -181,13 +181,20 @@ class PerfectTensorFlowTests: XCTestCase {
}

let n0 = def0.node
let n1 = def1.node // n1 may have two more operations: M1/M2, but gradients are the same
let n1 = def1.node
XCTAssertEqual(n0.count, n1.count)
for i in 0 ..< n0.count {
let a = n0[i]
let b = n1[i]
print(a.name, b.name)
XCTAssertEqual(a, b)
let n = n0[i]
let m = n1[i]
XCTAssertEqual(n.name, m.name)
XCTAssertEqual(n.op, m.op)
for key in n.attr.keys {
let v = n.attr[key]
let w = m.attr[key]
XCTAssertEqual(v, w)
}
}

}
public func buildSuccessGraph() throws ->
(graph: TF.Graph, inputs:[TF.Output], outputs: [TF.Output])
Expand All @@ -205,12 +212,12 @@ class PerfectTensorFlowTests: XCTestCase {
// | |
// Const_0 Const_1
//
let srcA:[Float] = [1,2,3,4]
let srcB:[Float] = [1,0,0,1]
let srcA:[[Float]] = [[1,2],[3,4]]
let srcB:[[Float]] = [[1,0],[0,1]]

// create tensors for these matrices
let tA = try TF.Tensor.Array(dimensions: [2,2], value: srcA)
let tB = try TF.Tensor.Array(dimensions: [2,2], value: srcB)
let tA = try TF.Tensor.Matrix(srcA)
let tB = try TF.Tensor.Matrix(srcB)

let g = try TF.Graph()
// adding tensors to graph
Expand Down Expand Up @@ -247,12 +254,12 @@ class PerfectTensorFlowTests: XCTestCase {
// | |
// | |
// Const_0 Const_1
let srcA:[Float] = [1,2,3,4]
let srcB:[Float] = [1,0,0,1]
let srcA:[[Float]] = [[1,2],[3,4]]
let srcB:[[Float]] = [[1,0],[0,1]]

// create tensors for these matrices
let tA = try TF.Tensor.Array(dimensions: [2,2], value: srcA)
let tB = try TF.Tensor.Array(dimensions: [2,2], value: srcB)
let tA = try TF.Tensor.Matrix(srcA)
let tB = try TF.Tensor.Matrix(srcB)

let g = try TF.Graph()
// adding tensors to graph
Expand All @@ -262,8 +269,8 @@ class PerfectTensorFlowTests: XCTestCase {

let C: TF.Operation
if providingDX {
let srcC: [Float] = [1, 1, 1, 1]
let tC = try TF.Tensor.Array(dimensions: [2,2], value: srcC)
let srcC: [[Float]] = [[1, 1], [1, 1]]
let tC = try TF.Tensor.Matrix(srcC)
C = try g.const(tensor: tC, name: "GradInputs")
} else {
C = try g.OnesLike(inp: M, name: "OnesLike")
Expand All @@ -276,8 +283,8 @@ class PerfectTensorFlowTests: XCTestCase {

public func addGradients(_ providingDX: Bool, graph: TF.Graph, inputs: [TF.Output], outputs: [TF.Output]) throws -> [TF.Output] {
if providingDX {
let dxArray:[Float] = [1,1,1,1]
let dxValue = try TF.Tensor.Array(dimensions: [2,2], value: dxArray)
let dxArray:[[Float]] = [[1, 1], [1, 1]]
let dxValue = try TF.Tensor.Matrix(dxArray)
let dx = try graph.const(tensor: dxValue, name: "GradInputs").asOutput(0)
return try graph.addGradients(y: outputs, x: inputs, dx: [dx])
} else {
Expand Down Expand Up @@ -1181,7 +1188,7 @@ class PerfectTensorFlowTests: XCTestCase {
}

func testVersion() {
XCTAssertEqual(TF.Version, "1.2.0")
XCTAssertEqual(TF.Version, "1.2.1")
}

func testSize() {
Expand Down
3 changes: 2 additions & 1 deletion install.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
OSABR=$(echo $(uname)|tr '[:upper:]' '[:lower:]')
DWN=/tmp/libtensorflow.tgz
URL=https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-cpu-$OSABR-x86_64-1.2.0.tar.gz
VERSION=1.2.1
URL=https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-cpu-$OSABR-x86_64-$VERSION.tar.gz
echo $URL
wget $URL -O $DWN
sudo tar xvf $DWN -C /usr/local ./lib/libtensorflow.so
Expand Down
5 changes: 3 additions & 2 deletions test.sh
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
# This script is for CI Server
VERSION=1.2.1
echo 'Clean Temp Files'
rm -rf /tmp/testdata
echo 'Unzip test pack'
tar xzf testpack.tgz -C /tmp/
if [[ $OSTYPE =~ darwin* ]]; then
echo 'get darwin library'
curl https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-cpu-darwin-x86_64-1.2.0.tar.gz -o /tmp/testdata/darwin.lib.tgz
curl https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-cpu-darwin-x86_64-$VERSION.tar.gz -o /tmp/testdata/darwin.lib.tgz
mkdir /tmp/testdata/darwin
echo 'expand darwin library'
tar xzf /tmp/testdata/darwin.lib.tgz -C /tmp/testdata/darwin
else
echo 'get linux library'
curl https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-cpu-linux-x86_64-1.2.0.tar.gz -o /tmp/testdata/linux.lib.tgz
curl https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-cpu-linux-x86_64-$VERSION.tar.gz -o /tmp/testdata/linux.lib.tgz
mkdir /tmp/testdata/linux
echo 'expand linux library'
tar xzf /tmp/testdata/linux.lib.tgz -C /tmp/testdata/linux
Expand Down

0 comments on commit 4944c8a

Please sign in to comment.