Structs as input to functions
calebwin opened this issue · 8 comments
The only things Emu functions can really accept right now are vectors (technically arrays/pointers) and primitive data (f32 or i32). Simple structures could be accepted with 2 changes.
-A change to the language so you can declare what kind of structs you accept and how to unpackage primitive data from them in the declaration of the Emu function
-A change to the build! macro to generate a function that can accept structs of a certain type and unpackage them into primitive data to send to the Emu function.
Before these changes are implemented, we should think about how the general interface to an Emu user should change. How should they pass structs to functions in a way that is most seamless.
Also, I think vectors of structs should also be allowed as input. Would that make sense?
Note that right now a function in Emu is basically something that is called for each element of a vector at least if you are using the build!
macro to generate Rust functions that do that for you. It is similar to how kernels in OpenCL are defined to operate on a single work-item.
Also, I think vectors of structs should also be allowed as input. Would that make sense?
Yes. Take a look at https://github.com/kpp/test_ocl/blob/master/src/main.rs#L11
Interesting.
struct Cluster {
input_ones: ocl::prm::Ulong2,
input_zeros: ocl::prm::Ulong2,
}
I don't think this is how a user should have to define structs. They should just be able to say-
struct Cluster {
input_ones: u64,
input_zeros: u64
}
Ulong2
- is a vector data type of two 64-bit unsigned integers. See https://www.khronos.org/registry/OpenCL/sdk/1.0/docs/man/xhtml/vectorDataTypes.html.
So Ulong2 != u64, it's like u128.
Ok. By the way, the "vectors" that Emu functions accept are not OpenCL vectors, they are arrays/pointers. So there isn't yet support for vector data types.
Strangely enough, when I googled gpu integer, one of the first relevant results was quasar which supports integer types.
https://gepura.io/quasar/quick-reference-manual/
2.2.2 Integer types
I did notice you mentioned not only supporting f32 but i32 integers also. I gave i32 a try.
error: expected 32-bit floating point number
--> emu_examples/arithmetic/src/main.rs:50:31
|
50 | data4[i] = data4[i] + 1; //it has to be a 32-bit integer
| ^
diff --git a/emu_examples/arithmetic/src/main.rs b/emu_examples/arithmetic/src/main.rs
index 415f928..249496b 100644
--- a/emu_examples/arithmetic/src/main.rs
+++ b/emu_examples/arithmetic/src/main.rs
@@ -1,15 +1,63 @@
use em::*;
+use std::string::String;
#[gpu_use]
-fn main() {
- let mut data = vec![0.1; 1000];
+fn do_it() {
+ let mut data1 = vec![1.0; 1000];
+ let mut data2 = vec![2.0; 1000];
+ let mut data3 = vec![3.0; 1000];
+
+ gpu_do!(load(data1));
+ gpu_do!(load(data2));
+ gpu_do!(load(data3));
+
+ gpu_do!(launch());
+ for i in 0..1000 {
+ data1[i] = data1[i] * data2[i]; //gives 2.0 everywhere
+ }
+ gpu_do!(read(data1));
+
+ gpu_do!(launch());
+ for i in 0..1000 {
+ data2[i] = data2[i] * data3[i]; //gives 6.0 everywhere
+ }
+ gpu_do!(read(data2));
- gpu_do!(load(data));
gpu_do!(launch());
for i in 0..1000 {
- data[i] = data[i] * 10.0;
+ data3[i] = data3[i] * data2[i]; //gives 18.0 everywhere
}
- gpu_do!(read(data));
+ gpu_do!(read(data3));
+
+ //let mut data4 = vec![0.0; 1000];
+ let mut data4: Vec<i32> = vec![0; 1000];
+
+ //strings which are composed of u8 bytes
+ //need to convert the entire array of u8 bytes
+ //into an array of f32 in order for the gpu to use it.
+ let mut data4_string = String::from("hello");
+ let mut data4_bytes = data4_string.into_bytes();
+ println!("data4_bytes:<<{:?}>>", data4_bytes);
+ for i in 0..5 {
+ //data4[i] = data4_bytes[i] as f32; //it has to be a 32-bit float
+ data4[i] = data4_bytes[i] as i32; //it has to be a 32-bit integer
+ }
+ println!("data4:<<{:?}>>", data4);
- println!("{:?}", data);
-}
+ gpu_do!(load(data4));
+ gpu_do!(launch());
+ for i in 0..5 {
+ //data4[i] = data4[i] + 1.0; //it has to be a 32-bit float
+ data4[i] = data4[i] + 1; //it has to be a 32-bit integer
+ }
+ gpu_do!(read(data4));
+
+ println!("data1:<<{:?}>>", data1);
+ println!("data2:<<{:?}>>", data2);
+ println!("data3:<<{:?}>>", data3);
+ println!("data4:<<{:?}>>", data4);
+}
+
+fn main() {
+ do_it();
+}
I wish there was more support for dealing with string handling within the gpu with emu. sorting/slicing/regex'ing.
Also, i32
and many other types were supported in 0.2.0. 0.3.0 removed f32
because of significant design changes to focus on safety and performance.