CooCoo 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/CooCoo.gemspec +47 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +88 -0
- data/README.md +123 -0
- data/Rakefile +81 -0
- data/bin/cuda-dev-info +25 -0
- data/bin/cuda-free +28 -0
- data/bin/cuda-free-trend +7 -0
- data/bin/ffi-gen +267 -0
- data/bin/spec_runner_html.sh +42 -0
- data/bin/trainer +198 -0
- data/bin/trend-cost +13 -0
- data/examples/char-rnn.rb +405 -0
- data/examples/cifar/cifar.rb +94 -0
- data/examples/img-similarity.rb +201 -0
- data/examples/math_ops.rb +57 -0
- data/examples/mnist.rb +365 -0
- data/examples/mnist_classifier.rb +293 -0
- data/examples/mnist_dream.rb +214 -0
- data/examples/seeds.rb +268 -0
- data/examples/seeds_dataset.txt +210 -0
- data/examples/t10k-images-idx3-ubyte +0 -0
- data/examples/t10k-labels-idx1-ubyte +0 -0
- data/examples/train-images-idx3-ubyte +0 -0
- data/examples/train-labels-idx1-ubyte +0 -0
- data/ext/buffer/Rakefile +50 -0
- data/ext/buffer/buffer.pre.cu +727 -0
- data/ext/buffer/matrix.pre.cu +49 -0
- data/lib/CooCoo.rb +1 -0
- data/lib/coo-coo.rb +18 -0
- data/lib/coo-coo/activation_functions.rb +344 -0
- data/lib/coo-coo/consts.rb +5 -0
- data/lib/coo-coo/convolution.rb +298 -0
- data/lib/coo-coo/core_ext.rb +75 -0
- data/lib/coo-coo/cost_functions.rb +91 -0
- data/lib/coo-coo/cuda.rb +116 -0
- data/lib/coo-coo/cuda/device_buffer.rb +240 -0
- data/lib/coo-coo/cuda/device_buffer/ffi.rb +109 -0
- data/lib/coo-coo/cuda/error.rb +51 -0
- data/lib/coo-coo/cuda/host_buffer.rb +117 -0
- data/lib/coo-coo/cuda/runtime.rb +157 -0
- data/lib/coo-coo/cuda/vector.rb +315 -0
- data/lib/coo-coo/data_sources.rb +2 -0
- data/lib/coo-coo/data_sources/xournal.rb +25 -0
- data/lib/coo-coo/data_sources/xournal/bitmap_stream.rb +197 -0
- data/lib/coo-coo/data_sources/xournal/document.rb +377 -0
- data/lib/coo-coo/data_sources/xournal/loader.rb +144 -0
- data/lib/coo-coo/data_sources/xournal/renderer.rb +101 -0
- data/lib/coo-coo/data_sources/xournal/saver.rb +99 -0
- data/lib/coo-coo/data_sources/xournal/training_document.rb +78 -0
- data/lib/coo-coo/data_sources/xournal/training_document/constants.rb +15 -0
- data/lib/coo-coo/data_sources/xournal/training_document/document_maker.rb +89 -0
- data/lib/coo-coo/data_sources/xournal/training_document/document_reader.rb +105 -0
- data/lib/coo-coo/data_sources/xournal/training_document/example.rb +37 -0
- data/lib/coo-coo/data_sources/xournal/training_document/sets.rb +76 -0
- data/lib/coo-coo/debug.rb +8 -0
- data/lib/coo-coo/dot.rb +129 -0
- data/lib/coo-coo/drawing.rb +4 -0
- data/lib/coo-coo/drawing/cairo_canvas.rb +100 -0
- data/lib/coo-coo/drawing/canvas.rb +68 -0
- data/lib/coo-coo/drawing/chunky_canvas.rb +101 -0
- data/lib/coo-coo/drawing/sixel.rb +214 -0
- data/lib/coo-coo/enum.rb +17 -0
- data/lib/coo-coo/from_name.rb +58 -0
- data/lib/coo-coo/fully_connected_layer.rb +205 -0
- data/lib/coo-coo/generation_script.rb +38 -0
- data/lib/coo-coo/grapher.rb +140 -0
- data/lib/coo-coo/image.rb +286 -0
- data/lib/coo-coo/layer.rb +67 -0
- data/lib/coo-coo/layer_factory.rb +26 -0
- data/lib/coo-coo/linear_layer.rb +59 -0
- data/lib/coo-coo/math.rb +607 -0
- data/lib/coo-coo/math/abstract_vector.rb +121 -0
- data/lib/coo-coo/math/functions.rb +39 -0
- data/lib/coo-coo/math/interpolation.rb +7 -0
- data/lib/coo-coo/network.rb +264 -0
- data/lib/coo-coo/neuron.rb +112 -0
- data/lib/coo-coo/neuron_layer.rb +168 -0
- data/lib/coo-coo/option_parser.rb +18 -0
- data/lib/coo-coo/platform.rb +17 -0
- data/lib/coo-coo/progress_bar.rb +11 -0
- data/lib/coo-coo/recurrence/backend.rb +99 -0
- data/lib/coo-coo/recurrence/frontend.rb +101 -0
- data/lib/coo-coo/sequence.rb +187 -0
- data/lib/coo-coo/shell.rb +2 -0
- data/lib/coo-coo/temporal_network.rb +291 -0
- data/lib/coo-coo/trainer.rb +21 -0
- data/lib/coo-coo/trainer/base.rb +67 -0
- data/lib/coo-coo/trainer/batch.rb +82 -0
- data/lib/coo-coo/trainer/batch_stats.rb +27 -0
- data/lib/coo-coo/trainer/momentum_stochastic.rb +59 -0
- data/lib/coo-coo/trainer/stochastic.rb +47 -0
- data/lib/coo-coo/transformer.rb +272 -0
- data/lib/coo-coo/vector_layer.rb +194 -0
- data/lib/coo-coo/version.rb +3 -0
- data/lib/coo-coo/weight_deltas.rb +23 -0
- data/prototypes/convolution.rb +116 -0
- data/prototypes/linear_drop.rb +51 -0
- data/prototypes/recurrent_layers.rb +79 -0
- data/www/images/screamer.png +0 -0
- data/www/images/screamer.xcf +0 -0
- data/www/index.html +82 -0
- metadata +373 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 98b06c828793e0ecc63255ac42b21b1860bb392d
|
|
4
|
+
data.tar.gz: d280b835315f6de205602b40150c6d68e638a42d
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 265aef5a22270f7476fae2327e9f0f0d03817a74026c85701ecfb444e468a6ff475b0f58f9ecdaeb03f802d041d29d63716d7e4df9e6695c044099c01d966683
|
|
7
|
+
data.tar.gz: 595de49ff692e78f5b49ddcf01ae510fde8f0227253d00f3b67f9fe6b1a5b2ba533589f14035d006b363bc8b50f39c2e58e6ff6c6c0c1b38345bf8104a9ed693
|
data/.gitignore
ADDED
data/CooCoo.gemspec
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
+
require 'coo-coo/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |s|
|
|
7
|
+
s.name = "CooCoo"
|
|
8
|
+
s.version = CooCoo::VERSION
|
|
9
|
+
s.platform = Gem::Platform::RUBY
|
|
10
|
+
s.authors = ["Nolan Eakins"]
|
|
11
|
+
s.email = ["sneakin+coocoo@semanticgap.com"]
|
|
12
|
+
s.homepage = "https://CooCoo.network/"
|
|
13
|
+
s.summary = "Neural networks in Ruby and CUDA."
|
|
14
|
+
s.license = "GPL"
|
|
15
|
+
|
|
16
|
+
if s.respond_to?(:metadata)
|
|
17
|
+
s.metadata['yard.run'] = 'yri'
|
|
18
|
+
else
|
|
19
|
+
raise "RubyGems 2.0 or newer is required to protect against " \
|
|
20
|
+
"public gem pushes."
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
s.files = `git ls-files -z`.split("\x0").reject do |f|
|
|
24
|
+
f.match(%r{^(test|spec|features)/})
|
|
25
|
+
end
|
|
26
|
+
s.bindir = "bin"
|
|
27
|
+
s.executables = s.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
28
|
+
s.require_paths = ["lib"]
|
|
29
|
+
|
|
30
|
+
s.add_development_dependency "bundler", "~> 1.14"
|
|
31
|
+
s.add_development_dependency "rake", "~> 10.0"
|
|
32
|
+
s.add_development_dependency "rspec", "~> 3.0"
|
|
33
|
+
s.add_development_dependency "yard"
|
|
34
|
+
s.add_development_dependency "yard-rspec"
|
|
35
|
+
s.add_development_dependency "pry", "~> 0.11.3"
|
|
36
|
+
s.add_development_dependency 'simplecov'
|
|
37
|
+
s.add_development_dependency 'coderay'
|
|
38
|
+
|
|
39
|
+
s.add_dependency 'nmatrix'
|
|
40
|
+
s.add_dependency 'parallel'
|
|
41
|
+
s.add_dependency 'nokogiri'
|
|
42
|
+
s.add_dependency 'ruby-progressbar'
|
|
43
|
+
s.add_dependency 'chunky_png'
|
|
44
|
+
s.add_dependency 'cairo'
|
|
45
|
+
s.add_dependency 'colorize'
|
|
46
|
+
s.add_dependency 'ffi'
|
|
47
|
+
end
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
CooCoo (0.1.0)
|
|
5
|
+
cairo
|
|
6
|
+
chunky_png
|
|
7
|
+
colorize
|
|
8
|
+
ffi
|
|
9
|
+
nmatrix
|
|
10
|
+
nokogiri
|
|
11
|
+
parallel
|
|
12
|
+
ruby-progressbar
|
|
13
|
+
|
|
14
|
+
GEM
|
|
15
|
+
remote: http://rubygems.org/
|
|
16
|
+
specs:
|
|
17
|
+
backports (3.10.3)
|
|
18
|
+
cairo (1.15.11)
|
|
19
|
+
native-package-installer (>= 1.0.3)
|
|
20
|
+
pkg-config (>= 1.2.2)
|
|
21
|
+
cairo (1.15.11-x64-mingw32)
|
|
22
|
+
native-package-installer (>= 1.0.3)
|
|
23
|
+
pkg-config (>= 1.2.2)
|
|
24
|
+
chunky_png (1.3.8)
|
|
25
|
+
coderay (1.1.2)
|
|
26
|
+
colorize (0.8.1)
|
|
27
|
+
diff-lcs (1.3)
|
|
28
|
+
docile (1.1.5)
|
|
29
|
+
ffi (1.9.18)
|
|
30
|
+
ffi (1.9.18-x64-mingw32)
|
|
31
|
+
json (2.1.0)
|
|
32
|
+
method_source (0.9.0)
|
|
33
|
+
mini_portile2 (2.3.0)
|
|
34
|
+
native-package-installer (1.0.6)
|
|
35
|
+
nmatrix (0.2.4)
|
|
36
|
+
packable (~> 1.3, >= 1.3.5)
|
|
37
|
+
nokogiri (1.8.1)
|
|
38
|
+
mini_portile2 (~> 2.3.0)
|
|
39
|
+
nokogiri (1.8.1-x64-mingw32)
|
|
40
|
+
mini_portile2 (~> 2.3.0)
|
|
41
|
+
packable (1.3.9)
|
|
42
|
+
backports
|
|
43
|
+
parallel (1.12.1)
|
|
44
|
+
pkg-config (1.2.8)
|
|
45
|
+
pry (0.11.3)
|
|
46
|
+
coderay (~> 1.1.0)
|
|
47
|
+
method_source (~> 0.9.0)
|
|
48
|
+
rake (10.5.0)
|
|
49
|
+
rspec (3.7.0)
|
|
50
|
+
rspec-core (~> 3.7.0)
|
|
51
|
+
rspec-expectations (~> 3.7.0)
|
|
52
|
+
rspec-mocks (~> 3.7.0)
|
|
53
|
+
rspec-core (3.7.0)
|
|
54
|
+
rspec-support (~> 3.7.0)
|
|
55
|
+
rspec-expectations (3.7.0)
|
|
56
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
57
|
+
rspec-support (~> 3.7.0)
|
|
58
|
+
rspec-mocks (3.7.0)
|
|
59
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
60
|
+
rspec-support (~> 3.7.0)
|
|
61
|
+
rspec-support (3.7.0)
|
|
62
|
+
ruby-progressbar (1.9.0)
|
|
63
|
+
simplecov (0.15.1)
|
|
64
|
+
docile (~> 1.1.0)
|
|
65
|
+
json (>= 1.8, < 3)
|
|
66
|
+
simplecov-html (~> 0.10.0)
|
|
67
|
+
simplecov-html (0.10.2)
|
|
68
|
+
yard (0.9.12)
|
|
69
|
+
yard-rspec (0.1)
|
|
70
|
+
yard
|
|
71
|
+
|
|
72
|
+
PLATFORMS
|
|
73
|
+
ruby
|
|
74
|
+
x64-mingw32
|
|
75
|
+
|
|
76
|
+
DEPENDENCIES
|
|
77
|
+
CooCoo!
|
|
78
|
+
bundler (~> 1.14)
|
|
79
|
+
coderay
|
|
80
|
+
pry (~> 0.11.3)
|
|
81
|
+
rake (~> 10.0)
|
|
82
|
+
rspec (~> 3.0)
|
|
83
|
+
simplecov
|
|
84
|
+
yard
|
|
85
|
+
yard-rspec
|
|
86
|
+
|
|
87
|
+
BUNDLED WITH
|
|
88
|
+
1.15.4
|
data/README.md
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
CooCoo
|
|
2
|
+
==========
|
|
3
|
+
|
|
4
|
+
Copyright © 2017-2018 [Nolan Eakins](mailto:sneakin+at+semanticgap.com)
|
|
5
|
+
|
|
6
|
+
THIS IS NOT PRODUCTION QUALITY. USE AT YOUR OWN RISK.
|
|
7
|
+
|
|
8
|
+
[Home page](https://coocoo.network/)
|
|
9
|
+
[GitHub](https://github.com/sneakin/CooCoo/)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
Description
|
|
13
|
+
----------
|
|
14
|
+
|
|
15
|
+
A neural network library implemented in Ruby with a CUDA backend.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
Dependencies
|
|
19
|
+
-------------
|
|
20
|
+
|
|
21
|
+
* [NVIDIA's CUDA Toolkit](https://developer.nvidia.com/cuda-downloads)
|
|
22
|
+
* Any one of the following C/C++ environments:
|
|
23
|
+
* [GCC](https://gcc.gnu.org/)
|
|
24
|
+
* [MSYS2](http://www.msys2.org/)
|
|
25
|
+
* [Ruby](https://www.ruby-lang.org/): install via your distribution package manager or MSYS2's `pacman -S ruby`
|
|
26
|
+
* [Bundler](http://bundler.io/)
|
|
27
|
+
* [Cairo](https://www.cairographics.org/rcairo/)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
Usage
|
|
31
|
+
----------
|
|
32
|
+
|
|
33
|
+
### Coming soon
|
|
34
|
+
|
|
35
|
+
$ gem install CooCoo
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
### Install
|
|
39
|
+
|
|
40
|
+
First the required dependencies need to be installed. The dependencies include the CUDA compiler and RubyGems.
|
|
41
|
+
|
|
42
|
+
Once the CUDA toolkit is installed, make sure it and Visual Studio's C++ compiler are in your path. Under MSYS2, use something like:
|
|
43
|
+
|
|
44
|
+
$ export PATH=/c/Program\ Files\ \(x86\)/Microsoft\ Visual\ Studio/2017/Community/VC/Tools/MSVC/14.10.25017/bin/HostX64/x64:$PATH
|
|
45
|
+
$ export PATH=/c/Program\ Files/NVIDIA\ GPU\ Computing\ Toolkit/CUDA/v9.0/bin:$PATH
|
|
46
|
+
|
|
47
|
+
RubyGems are installed with Bundler: `bundle install`
|
|
48
|
+
|
|
49
|
+
And the extension is built with: `rake compile`
|
|
50
|
+
|
|
51
|
+
Then to run an example: `bundle exec ruby -Ilib -Iexamples examples/seeds.rb`
|
|
52
|
+
|
|
53
|
+
Or IRB: `bundle exec irb -Ilib`
|
|
54
|
+
|
|
55
|
+
Or IRB: `bundle exec ruby -Ilib`
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
### Code
|
|
59
|
+
|
|
60
|
+
```ruby
|
|
61
|
+
require 'coo-coo'
|
|
62
|
+
|
|
63
|
+
network = CooCoo::Network.new()
|
|
64
|
+
# create the layers
|
|
65
|
+
network.layer(CooCoo::Layer.new(28 * 28, 100))
|
|
66
|
+
network.layer(CooCoo::Layer.new(100, 10))
|
|
67
|
+
|
|
68
|
+
# learn
|
|
69
|
+
training_data = [ [expected_output, input_data_array ], ...]
|
|
70
|
+
|
|
71
|
+
trainer = CooCoo::Trainer::Stochastic.new
|
|
72
|
+
trainer.train(network: network,
|
|
73
|
+
data: training_data,
|
|
74
|
+
learning_rate: learning_rate,
|
|
75
|
+
batch_size: batch_size) do |stats|
|
|
76
|
+
# called every batch_size
|
|
77
|
+
puts("Batch #{batch} took #{stats.total_time} seconds with an average loss of #{stats.average_loss}.")
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# store to disk
|
|
81
|
+
network.save("my_first_network.coo-coo_model")
|
|
82
|
+
|
|
83
|
+
# load from disk
|
|
84
|
+
loaded_net = CooCoo::Network.load!("my_first_network.coo-coo_model")
|
|
85
|
+
|
|
86
|
+
# predict
|
|
87
|
+
output = loaded_network.predict([ 0, 0, 0, ... ])
|
|
88
|
+
# => [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Examples
|
|
93
|
+
----------
|
|
94
|
+
|
|
95
|
+
All examples use `OptParse`, so refer to the output of running the example with `--help`. With no arguments, typically a network will be generated, trained, and tested without saving.
|
|
96
|
+
|
|
97
|
+
To run an example: `bundle exec ruby -Ilib -Iexamples examples/EXAMPLE.rb --help`
|
|
98
|
+
|
|
99
|
+
### [char-rnn](examples/char-rnn.rb)
|
|
100
|
+
|
|
101
|
+
A recursive network that learns byte sequences.
|
|
102
|
+
|
|
103
|
+
### [UCI Wheat Seed Classifier](examples/seeds.rb)
|
|
104
|
+
|
|
105
|
+
Inspired by the IBAFSIP, this uses the UCI Machine Learning Repository's [wheat seed dataset](http://archive.ics.uci.edu/ml/datasets/seeds) to predict the type of seed given seven parameters.
|
|
106
|
+
|
|
107
|
+
### [MNIST Classifier](examples/mnist_classifier.rb)
|
|
108
|
+
|
|
109
|
+
[The MNIST Database](http://yann.lecun.com/exdb/mnist/) is used to train a 10 digit classifier.
|
|
110
|
+
|
|
111
|
+
### [MNIST Dream](examples/mnist_dream.rb)
|
|
112
|
+
|
|
113
|
+
Uses a network trained with the MNIST Classifier to generate valid inputs via backpropagation.
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
Credits
|
|
117
|
+
----------
|
|
118
|
+
|
|
119
|
+
Loosely based on [Implement Backpropagation Algorithm From Scratch in Python](http://machinelearningmastery.com/implement-backpropagation-algorithm-scratch-python/)
|
|
120
|
+
|
|
121
|
+
And more than a few of [Siraj Raval's videos](https://www.youtube.com/channel/UCWN3xxRkmTPmbKwht9FuE5A)
|
|
122
|
+
|
|
123
|
+
Cross entropy & Softmax sorted out with [DeepNotes.io](https://deepnotes.io/softmax-crossentropy)
|
data/Rakefile
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
require 'bundler/gem_tasks'
|
|
2
|
+
|
|
3
|
+
task :default => [ 'spec:coverage', 'doc' ]
|
|
4
|
+
|
|
5
|
+
desc "Clean any output files."
|
|
6
|
+
task :clean => :clean_ext do
|
|
7
|
+
sh("rm -rf doc/coverage doc/rdoc doc/spec.html doc/api")
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
task :clean_ext do
|
|
11
|
+
Dir.glob("ext/*").each do |entry|
|
|
12
|
+
sh("cd #{entry}; rake clean") if File.exists?(File.join(entry, "Rakefile"))
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
desc "Compile the extensions."
|
|
17
|
+
if ENV["USE_CUDA"] != "0"
|
|
18
|
+
task :compile => "ext/buffer/Rakefile" do |t|
|
|
19
|
+
pwd = Dir.pwd
|
|
20
|
+
Dir.chdir(File.dirname(t.source))
|
|
21
|
+
sh("rake")
|
|
22
|
+
Dir.chdir(pwd)
|
|
23
|
+
end
|
|
24
|
+
else
|
|
25
|
+
task :compile do
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
desc 'Create the YARDocs'
|
|
30
|
+
require 'yard'
|
|
31
|
+
YARD::Rake::YardocTask.new(:doc) do |t|
|
|
32
|
+
t.files = [ 'lib/**/*.rb', 'examples/**/*.rb', 'spec/**/*.spec', '-', 'README.md' ]
|
|
33
|
+
t.options = [ '--plugin', 'rspec', '-o', 'doc/api' ]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
desc "Run the rspecs."
|
|
37
|
+
require 'rspec/core/rake_task'
|
|
38
|
+
RSpec::Core::RakeTask.new(:spec => :compile) do |t, args|
|
|
39
|
+
t.pattern = "spec/**/*.spec"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
namespace :spec do
|
|
43
|
+
desc "Run the specs with HTML output."
|
|
44
|
+
RSpec::Core::RakeTask.new(:html => :compile) do |t, args|
|
|
45
|
+
t.pattern = "spec/**/*.spec"
|
|
46
|
+
t.rspec_opts = '-fhtml -o doc/spec.html'
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
desc "Run the specs with code coverage."
|
|
50
|
+
task :coverage => :compile do
|
|
51
|
+
ENV['COVERAGE'] = 'true'
|
|
52
|
+
Rake::Task['spec:html'].execute
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
desc "Run Ruby with everything in the search paths."
|
|
57
|
+
task :run => :compile do
|
|
58
|
+
args = $*[1, $*.size - 1]
|
|
59
|
+
exec("bundle exec ruby -Ilib -Iexamples #{args.join(' ')}")
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
desc "Start an IRB session with everything loaded."
|
|
63
|
+
task :shell => :compile do
|
|
64
|
+
exec("bundle exec irb -Ilib -Iexamples -rcoo-coo/shell")
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
desc "Start a Pry session with everything loaded."
|
|
68
|
+
task :pry => :compile do
|
|
69
|
+
exec("bundle exec pry -Ilib -Iexamples -rcoo-coo/shell")
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
namespace :www do
|
|
73
|
+
desc "Upload the website"
|
|
74
|
+
task :upload do
|
|
75
|
+
user = ENV.fetch("COOCOO_USER")
|
|
76
|
+
sh("ssh #{user}@coocoo.network mkdir -p \\~/www/coocoo.network/public/images")
|
|
77
|
+
sh("scp www/index.html #{user}@coocoo.network:~/www/coocoo.network/public/index.html")
|
|
78
|
+
sh("scp www/images/screamer.png #{user}@coocoo.network:~/www/coocoo.network/public/images/screamer.png")
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
data/bin/cuda-dev-info
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/bin/env ruby
|
|
2
|
+
|
|
3
|
+
$: << File.join(File.dirname(__FILE__), '..', 'lib')
|
|
4
|
+
require 'coo-coo/cuda'
|
|
5
|
+
|
|
6
|
+
unless CooCoo::CUDA.available?
|
|
7
|
+
puts("Cuda not available")
|
|
8
|
+
exit(-1)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
puts("Device\t#{CooCoo::CUDA::Runtime.get_device} / #{CooCoo::CUDA::Runtime.device_count}")
|
|
12
|
+
props = CooCoo::CUDA::Runtime::DeviceProperties.new
|
|
13
|
+
err = CooCoo::CUDA::Runtime.cudaGetDeviceProperties(props, 0)
|
|
14
|
+
raise CUDAError(err) if err != 0
|
|
15
|
+
|
|
16
|
+
props.members.each do |m|
|
|
17
|
+
value = props[m]
|
|
18
|
+
if m != :name && value.kind_of?(FFI::Struct::InlineArray)
|
|
19
|
+
value.each_with_index do |v, i|
|
|
20
|
+
puts("#{m}[#{i}]\t#{v}")
|
|
21
|
+
end
|
|
22
|
+
else
|
|
23
|
+
puts("#{m}\t#{value}")
|
|
24
|
+
end
|
|
25
|
+
end
|
data/bin/cuda-free
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/bin/env ruby
|
|
2
|
+
|
|
3
|
+
$: << File.join(File.dirname(__FILE__), '..', 'lib')
|
|
4
|
+
require 'coo-coo/cuda'
|
|
5
|
+
|
|
6
|
+
require 'ostruct'
|
|
7
|
+
options = OpenStruct.new
|
|
8
|
+
options.follow = ARGV[0] == '-f'
|
|
9
|
+
options.timeout = (ARGV[1] || 1).to_f
|
|
10
|
+
|
|
11
|
+
unless options.follow
|
|
12
|
+
puts("Device\tBytes Free\tBytes Total\tPercent")
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
follow = true
|
|
16
|
+
$stdout.sync = true
|
|
17
|
+
|
|
18
|
+
while follow
|
|
19
|
+
follow = options.follow
|
|
20
|
+
CooCoo::CUDA::Runtime.device_count.times do |device|
|
|
21
|
+
CooCoo::CUDA::Runtime.set_device(device)
|
|
22
|
+
free, total = CooCoo::CUDA.memory_info
|
|
23
|
+
$stdout.puts("%i\t%i\t%i\t%.3f" % [ device, free, total, (100.0 * free / total.to_f) ])
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
$stdout.flush
|
|
27
|
+
sleep(options.timeout)
|
|
28
|
+
end
|
data/bin/cuda-free-trend
ADDED
data/bin/ffi-gen
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
#!/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'ffi'
|
|
4
|
+
|
|
5
|
+
class ExportScanner
|
|
6
|
+
NEEDLE = "PUBLIC"
|
|
7
|
+
NVCCFLAGS = []
|
|
8
|
+
|
|
9
|
+
attr_reader :structs
|
|
10
|
+
attr_reader :functions
|
|
11
|
+
|
|
12
|
+
def initialize(typedefs = Hash.new)
|
|
13
|
+
@functions = Array.new
|
|
14
|
+
@structs = Array.new
|
|
15
|
+
@typedefs = typedefs
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
FunctionPrototype = Struct.new(:name, :return_type, :args, :definition)
|
|
19
|
+
|
|
20
|
+
class Argument
|
|
21
|
+
attr_accessor :const
|
|
22
|
+
attr_accessor :type
|
|
23
|
+
attr_accessor :name
|
|
24
|
+
attr_accessor :pointer
|
|
25
|
+
|
|
26
|
+
def initialize(str)
|
|
27
|
+
m = str.match(/\s*(((\w+) )+\s*(([*]+)?(\w+)?)\s*)/m)
|
|
28
|
+
if m
|
|
29
|
+
self.name = m[-1]
|
|
30
|
+
self.const = m[0] =~ /const/
|
|
31
|
+
self.pointer = m[-2]
|
|
32
|
+
self.type = m[3]
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def parse_args(arg_str)
|
|
38
|
+
args = arg_str.split(',').collect(&:strip)
|
|
39
|
+
arg_types = args.collect do |a|
|
|
40
|
+
Argument.new(a)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def scan_function(f)
|
|
45
|
+
m = f.match(/(\w+)\s+(\w+)\s*\((.*)\)/)
|
|
46
|
+
if m
|
|
47
|
+
func = m[2]
|
|
48
|
+
args = parse_args(m[3])
|
|
49
|
+
ret = m[1].strip
|
|
50
|
+
FunctionPrototype.new(func, ret, args, f)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def scan_for_functions(path)
|
|
55
|
+
`nvcc -E -DIN_PUBLIC=1 -D#{NEEDLE}=#{NEEDLE} #{NVCCFLAGS.join(' ')} #{path} | grep -e '#{NEEDLE}'`.
|
|
56
|
+
split("\n").
|
|
57
|
+
collect { |f| m = f.match(/(#{NEEDLE}.*[)]([^;]|$))/); m && m[1] }.
|
|
58
|
+
reject(&:nil?).
|
|
59
|
+
collect { |f| scan_function(f[0, f.index(')') + 1]) }
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
StructDef = Struct.new(:name, :definition, :fields)
|
|
63
|
+
StructField = Struct.new(:name, :definition, :type, :pointer)
|
|
64
|
+
|
|
65
|
+
def scan_struct_field(field)
|
|
66
|
+
m = field.match(/\s*(((\w+) )+\s*(([*]+)?(\w+))\s*)/m)
|
|
67
|
+
if m
|
|
68
|
+
StructField.new(m[-1], field, m[2].strip, m[-2])
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def scan_struct_fields(fields)
|
|
73
|
+
fields.collect { |field| scan_struct_field(field) }.reject(&:nil?)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def scan_for_structs_inner(data, acc = [])
|
|
77
|
+
m = data.match(/(typedef\s+struct\s+(\w+)\s+{(.*)}\s+[*](\w+);)(.*)/m)
|
|
78
|
+
if m
|
|
79
|
+
acc << StructDef.new(m[4], m[1], scan_struct_fields(m[3].split(';').collect(&:strip)))
|
|
80
|
+
scan_for_structs_inner(m[5], acc)
|
|
81
|
+
else
|
|
82
|
+
acc
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def scan_for_structs(path)
|
|
87
|
+
scan_for_structs_inner(File.read(path))
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def scan(path)
|
|
91
|
+
@functions += scan_for_functions(path)
|
|
92
|
+
@structs += scan_for_structs(path)
|
|
93
|
+
|
|
94
|
+
self
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def header(name)
|
|
98
|
+
head = File.basename(name).upcase
|
|
99
|
+
<<-EOT
|
|
100
|
+
\#ifndef #{head}
|
|
101
|
+
\#define #{head}
|
|
102
|
+
|
|
103
|
+
\#include "public.h"
|
|
104
|
+
|
|
105
|
+
extern "C" {
|
|
106
|
+
#{structs.collect(&:definition).join('\n')}
|
|
107
|
+
|
|
108
|
+
#{functions.collect(&:definition).join(";\n ")};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
\#endif /* #{head} */
|
|
112
|
+
EOT
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def ffi_type(a, pointer = nil)
|
|
116
|
+
a = @typedefs[a] if @typedefs.has_key?(a)
|
|
117
|
+
if FFI::TypeDefs[a.to_sym]
|
|
118
|
+
":" + FFI::TypeDefs.key(FFI::TypeDefs[a.to_sym]).to_s
|
|
119
|
+
elsif pointer
|
|
120
|
+
"#{a}.auto_ptr"
|
|
121
|
+
else
|
|
122
|
+
a
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def ffi_def(f)
|
|
127
|
+
func = f.name
|
|
128
|
+
args = f.args.collect do |a|
|
|
129
|
+
if a.pointer
|
|
130
|
+
":pointer"
|
|
131
|
+
else
|
|
132
|
+
ffi_type(a.type)
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
ret = f.return_type
|
|
137
|
+
ret = ffi_type(ret, true)
|
|
138
|
+
|
|
139
|
+
" attach_function :#{func}, [ #{args.join(', ')} ], #{ret}"
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def ffi_struct(s)
|
|
143
|
+
layout = s.fields.collect { |f| [ ":#{f.name}", ffi_type(f.type, f.pointer) ] }
|
|
144
|
+
<<-EOT
|
|
145
|
+
class #{s.name} < ::FFI::Struct
|
|
146
|
+
layout(#{layout.join(', ')})
|
|
147
|
+
|
|
148
|
+
def self.release(ptr)
|
|
149
|
+
#{s.name.downcase}_free(ptr)
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
EOT
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def ffi(name, library)
|
|
156
|
+
<<-EOT
|
|
157
|
+
module #{name}
|
|
158
|
+
module FFI
|
|
159
|
+
extend ::FFI::Library
|
|
160
|
+
ffi_lib Pathname.new(__FILE__).join('..', "#{library}.#{RbConfig::CONFIG['DLEXT']}").to_s
|
|
161
|
+
|
|
162
|
+
#{structs.collect { |s| ffi_struct(s) }.compact.join("\n")}
|
|
163
|
+
#{functions.collect { |f| ffi_def(f) }.compact.join("\n")}
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
EOT
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def write_header(header, sources)
|
|
171
|
+
# empty the file for preprocessing
|
|
172
|
+
if header != nil && header != '-'
|
|
173
|
+
File.open(header, 'w') do |f|
|
|
174
|
+
f.puts
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
scanner = ExportScanner.new
|
|
179
|
+
sources.each(&-> (s) { scanner.scan(s) })
|
|
180
|
+
|
|
181
|
+
if header == nil || header == '-'
|
|
182
|
+
$stdout.puts(scanner.header("STDOUT"))
|
|
183
|
+
else
|
|
184
|
+
File.open(header, 'w') do |f|
|
|
185
|
+
f.puts(scanner.header(header.gsub('.', '_')))
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def write_ffi(mod, library, output, sources, typedefs)
|
|
191
|
+
raise ArgumentError.new('No --module name given.') if mod == nil
|
|
192
|
+
raise ArgumentError.new('No --library given.') if library == nil
|
|
193
|
+
|
|
194
|
+
scanner = ExportScanner.new(typedefs)
|
|
195
|
+
sources.each(&->(s) { scanner.scan(s) })
|
|
196
|
+
|
|
197
|
+
if output == nil || output == '-'
|
|
198
|
+
$stdout.puts(scanner.ffi(mod, library))
|
|
199
|
+
else
|
|
200
|
+
File.open(output, 'w') do |f|
|
|
201
|
+
f.puts(scanner.ffi(mod, library))
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
require 'fileutils'
|
|
207
|
+
def write_source(output, source)
|
|
208
|
+
FileUtils.copy(source, output)
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
if __FILE__ == $0
|
|
213
|
+
require 'ostruct'
|
|
214
|
+
options = OpenStruct.new
|
|
215
|
+
options.mode = :help
|
|
216
|
+
options.sources = Array.new
|
|
217
|
+
options.typedefs = Hash.new
|
|
218
|
+
|
|
219
|
+
require 'optparse'
|
|
220
|
+
opts = OptionParser.new() do |o|
|
|
221
|
+
o.on('-h', 'Help') do
|
|
222
|
+
options.mode = :help
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
o.on('--header', 'Generate a C/C++ header.') do
|
|
226
|
+
options.mode = :header
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
o.on('--ffi', 'Generate a Ruby FFI.') do
|
|
230
|
+
options.mode = :ffi
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
o.on('--source', 'Generate C/C++ source code.') do
|
|
234
|
+
options.mode = :source
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
o.on('-o', '--output PATH', 'Write the output to PATH.') do |path|
|
|
238
|
+
options.output = path
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
o.on('--module NAME', 'The name of the generated FFI module.') do |m|
|
|
242
|
+
options.module = m
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
o.on('-l', '--library NAME', 'The shared library name to load.') do |l|
|
|
246
|
+
options.library = l
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
o.on('-t', '--typedef TYPE=NAME') do |v|
|
|
250
|
+
type, name = v.split('=')
|
|
251
|
+
options.typedefs[name] = type if type && name
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
options.sources = opts.parse!(ARGV)
|
|
256
|
+
|
|
257
|
+
unless options.mode == :help
|
|
258
|
+
raise ArgumentError.new("No sources found.") unless options.sources.size > 0
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
case options.mode
|
|
262
|
+
when :ffi then write_ffi(options.module, options.library, options.output, options.sources, options.typedefs)
|
|
263
|
+
when :header then write_header(options.output, options.sources)
|
|
264
|
+
when :source then write_source(options.output, options.sources[0])
|
|
265
|
+
else puts(opts.help)
|
|
266
|
+
end
|
|
267
|
+
end
|