-
-
Notifications
You must be signed in to change notification settings - Fork 90
/
Copy pathHelpers.swift
100 lines (85 loc) · 3.9 KB
/
Helpers.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
//
// HelperExtensions.swift
// Bender
//
// Created by Joaquin Rocco on 11/30/16.
// Copyright © 2017 Xmartlabs. All rights reserved.
//
import Accelerate
/// Helper function to measure the time elapsed during the execution of a block of code
public func measure(_ label: String = "", _ block: () -> Void) {
let time1 = Date()
block()
let time2 = Date()
let v = time2.timeIntervalSince(time1)
debugPrint("\(label): \(v) (\(1/v) per second)")
}
/// Function that transposes weights in a certain order
public typealias TransposeFunction = (Data, Shape) -> (Data)
/// Transposes weights from HWIO to OHWI order. Used to pass TensorFlow's weights for Convolution layers
func HWIOtoOHWI(weights: Data, shape: Shape) -> Data {
var transposed = [Float](repeating: 0.0, count: shape.totalCount)
let weightsPointer: UnsafePointer<Float>! = weights.pointer()
for o in 0..<shape.outputChannels {
for h in 0..<shape.height {
for w in 0..<shape.width {
for i in 0..<shape.inputChannels {
let tIndex = i + shape.inputChannels * (w + shape.width * (h + shape.height * (o)))
let wIndex = o + shape.outputChannels * (i + shape.inputChannels * (w + shape.width * (h)))
transposed[tIndex] = weightsPointer[wIndex]
}
}
}
}
return Data(bytes: transposed, count: shape.totalCount * MemoryLayout<Float>.stride)
}
public func permute(order: [Int]) -> (_ weights: Data, _ shape: Shape) -> Data {
return { weights, shape in
var transposed = [Float](repeating: 0.0, count: shape.totalCount)
let weightsPointer: UnsafePointer<Float>! = weights.pointer()
var index = 0
var index_order = [0, 0, 0, 0]
for d in 0..<shape.at(order[0]) {
index_order[order[0]] = d
for c in 0..<shape.at(order[1]) {
index_order[order[1]] = c
for b in 0..<shape.at(order[2]) {
index_order[order[2]] = b
for a in 0..<shape.at(order[3]) {
index_order[order[3]] = a
let tIndex = index_order[3] + shape.at(3) * (index_order[2] + shape.at(2) * (index_order[1] + shape.at(1) * (index_order[0])))
transposed[index] = weightsPointer[tIndex]
index += 1
}
}
}
}
return Data(bytes: transposed, count: shape.totalCount * MemoryLayout<Float>.stride)
}
}
/// Transposes weights from HWIO to OHWI order. Used to pass TensorFlow's weights for Convolution layers
func HWIOtoIOWH(weights: Data, shape: Shape) -> Data {
var transposed = [Float](repeating: 0.0, count: shape.totalCount)
let weightsPointer: UnsafePointer<Float>! = weights.pointer()
for o in 0..<shape.outputChannels {
for h in 0..<shape.height {
for w in 0..<shape.width {
for i in 0..<shape.inputChannels {
let tIndex = h + shape.height * (w + shape.width * (o + shape.outputChannels * (i)))
let wIndex = o + shape.outputChannels * (i + shape.inputChannels * (w + shape.width * (h)))
transposed[tIndex] = weightsPointer[wIndex]
}
}
}
}
return Data(bytes: transposed, count: shape.totalCount * MemoryLayout<Float>.stride)
}
public func float32to16(_ input: UnsafeMutablePointer<Float>, count: Int) -> [UInt16] {
var output = [UInt16](repeating: 0, count: count)
var bufferFloat32 = vImage_Buffer(data: input, height: 1, width: UInt(count), rowBytes: count * 4)
var bufferFloat16 = vImage_Buffer(data: &output, height: 1, width: UInt(count), rowBytes: count * 2)
if vImageConvert_PlanarFtoPlanar16F(&bufferFloat32, &bufferFloat16, 0) != kvImageNoError {
fatalError("Error converting float32 to float16")
}
return output
}