Skip to content

Commit 2b898fd

Browse files
authored
Add OpenCL ruby samples (KhronosGroup#32)
* Add support for Ruby samples + CI * Renamed workflow Ruby tasks. * Added README.md for Ruby samples.
1 parent bda197c commit 2b898fd

File tree

6 files changed

+175
-0
lines changed

6 files changed

+175
-0
lines changed

.github/workflows/presubmit.yml

+25
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,28 @@ jobs:
9090
echo "-----------------------------------------------------------------------"
9191
time python $i
9292
done
93+
94+
checkruby:
95+
name: Check Ruby Samples ${{ matrix.os }}
96+
runs-on: ${{ matrix.os }}
97+
strategy:
98+
matrix:
99+
os: [ubuntu-latest, macos-latest]
100+
steps:
101+
- uses: actions/checkout@v2
102+
with:
103+
fetch-depth: 0
104+
submodules: recursive
105+
- name: Install Ruby and POCL
106+
run: sudo apt install pocl-opencl-icd
107+
if: ${{ matrix.os == 'ubuntu-latest' }}
108+
- name: Install OpenCL Ruby Bindings and RuboCop
109+
run: gem install --user-install opencl_ruby_ffi rubocop
110+
- name: Check Ruby Syntax
111+
run: |
112+
export PATH=`ruby -r rubygems -e 'puts Gem.user_dir'`/bin:$PATH
113+
rubocop
114+
working-directory: ruby
115+
- name: Run Ruby Samples
116+
run: rake test
117+
working-directory: ruby

ruby/README.md

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Ruby Samples
2+
3+
## Sample Purpose
4+
5+
Those samples reproduce the core samples using Ruby. They accept the same
6+
options, please refer to each core sample `README.md` for documentation.
7+
8+
## Prerequisites
9+
10+
In addition to a working Ruby installation, as well as Ruby development files,
11+
those samples require the `opencl_ruby_ffi` Ruby bindings. The bindings can be
12+
installed using:
13+
```bash
14+
gem install --user-install opencl_ruby_ffi
15+
```

ruby/copybuffer/copybuffer.rb

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# frozen_string_literal: true
2+
3+
require 'optparse'
4+
5+
options = { platform: 0, device: 0 }
6+
OptionParser.new do |parser|
7+
parser.banner = "Usage: ruby #{File.basename($PROGRAM_NAME)} [options]"
8+
parser.on('-p', '--platform INDEX', Integer, 'Index of the platform to use (default 0)')
9+
parser.on('-d', '--device INDEX', Integer, 'Index of the device to use (default 0)')
10+
end.parse!(into: options)
11+
12+
require 'opencl_ruby_ffi'
13+
14+
buffer_size = 1024 * 1024
15+
16+
p = OpenCL.platforms[options[:platform]]
17+
raise "Invalid platform index #{options[:platform]}" unless p
18+
19+
d = p.devices[options[:device]]
20+
raise "Invalid device index #{options[:device]}" unless d
21+
22+
puts "Running on platform: #{p.name}"
23+
puts "Running on device: #{d.name}"
24+
25+
c = OpenCL.create_context(d)
26+
q = c.create_command_queue(d)
27+
28+
device_src = c.create_buffer(buffer_size * OpenCL::UInt.size, flags: OpenCL::Mem::ALLOC_HOST_PTR)
29+
device_dst = c.create_buffer(buffer_size * OpenCL::UInt.size, flags: OpenCL::Mem::ALLOC_HOST_PTR)
30+
31+
_, host_ptr = q.enqueue_map_buffer(device_src, OpenCL::MapFlags::WRITE_INVALIDATE_REGION, blocking: true)
32+
host_ptr.write_array_of_uint(buffer_size.times.to_a)
33+
q.enqueue_unmap_mem_object(device_src, host_ptr)
34+
35+
q.enqueue_copy_buffer(device_src, device_dst)
36+
37+
_, host_ptr = q.enqueue_map_buffer(device_dst, OpenCL::MapFlags::READ, blocking: true)
38+
result = host_ptr.read_array_of_uint(buffer_size)
39+
buffer_size.times do |i|
40+
raise "invalid copy: wanted #{i}, got #{result[i]}" unless result[i] == i
41+
end
42+
q.enqueue_unmap_mem_object(device_dst, host_ptr)
43+
44+
puts 'Success.'
+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# frozen_string_literal: true
2+
3+
require 'optparse'
4+
5+
options = { platform: 0, device: 0 }
6+
OptionParser.new do |parser|
7+
parser.banner = "Usage: ruby #{File.basename($PROGRAM_NAME)} [options]"
8+
parser.on('-p', '--platform INDEX', Integer, 'Index of the platform to use (default 0)')
9+
parser.on('-d', '--device INDEX', Integer, 'Index of the device to use (default 0)')
10+
end.parse!(into: options)
11+
12+
require 'opencl_ruby_ffi'
13+
require 'narray_ffi'
14+
15+
kernel_string = <<~CLC
16+
kernel void CopyBuffer( global uint* dst, global uint* src )
17+
{
18+
uint id = get_global_id(0);
19+
dst[id] = src[id];
20+
}
21+
CLC
22+
23+
buffer_size = 1024 * 1024
24+
25+
p = OpenCL.platforms[options[:platform]]
26+
raise "Invalid platform index #{options[:platform]}" unless p
27+
28+
d = p.devices[options[:device]]
29+
raise "Invalid device index #{options[:device]}" unless d
30+
31+
puts "Running on platform: #{p.name}"
32+
puts "Running on device: #{d.name}"
33+
34+
begin
35+
c = OpenCL.create_context(d)
36+
q = c.create_command_queue(d)
37+
38+
program = c.create_program_with_source(kernel_string)
39+
program.build
40+
device_src = c.create_buffer(buffer_size * OpenCL::UInt.size, flags: OpenCL::Mem::ALLOC_HOST_PTR)
41+
device_dst = c.create_buffer(buffer_size * OpenCL::UInt.size, flags: OpenCL::Mem::ALLOC_HOST_PTR)
42+
43+
_, host_ptr = q.enqueue_map_buffer(device_src, OpenCL::MapFlags::WRITE_INVALIDATE_REGION, blocking: true)
44+
arr = NArray.to_na(host_ptr, NArray::INT)
45+
buffer_size.times { |i| arr[i] = i }
46+
q.enqueue_unmap_mem_object(device_src, host_ptr)
47+
48+
program.CopyBuffer(q, [buffer_size], device_dst, device_src)
49+
50+
_, host_ptr = q.enqueue_map_buffer(device_dst, OpenCL::MapFlags::READ, blocking: true)
51+
arr = NArray.to_na(host_ptr, NArray::INT)
52+
buffer_size.times do |i|
53+
raise "invalid copy: wanted #{i}, got #{arr[i]}" unless arr[i] == i
54+
end
55+
q.enqueue_unmap_mem_object(device_dst, host_ptr)
56+
57+
puts 'Success.'
58+
rescue OpenCL::Error::BUILD_PROGRAM_FAILURE
59+
puts 'Compilation of program failed:'
60+
program.build_log.each do |device, log|
61+
puts " - #{device.name}:"
62+
puts log
63+
end
64+
puts 'Expected Failure on MacOS...'
65+
end

ruby/enumopencl/enumopencl.rb

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# frozen_string_literal: true
2+
3+
require 'opencl_ruby_ffi'
4+
require 'yaml'
5+
6+
puts YAML.dump(
7+
{ 'platforms' => OpenCL.platforms.collect do |p|
8+
{ 'name' => p.name,
9+
'vendor' => p.vendor,
10+
'version' => p.version,
11+
'devices' => p.devices.collect do |d|
12+
{ 'name' => d.name,
13+
'type' => d.type.to_s,
14+
'vendor' => d.vendor,
15+
'version' => d.version,
16+
'profile' => d.profile,
17+
'driver_version' => d.driver_version }
18+
end }
19+
end }
20+
)

ruby/rakefile

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# frozen_string_literal: true
2+
3+
require 'rake/testtask'
4+
Rake::TestTask.new do |t|
5+
t.pattern = '**/*.rb'
6+
end

0 commit comments

Comments
 (0)