Skip to content

API Catchup to 3.3.0 version #59

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 12, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "arrayfire"
description = "ArrayFire is a high performance software library for parallel computing with an easy-to-use API. Its array based function set makes parallel programming simple. ArrayFire's multiple backends (CUDA, OpenCL and native CPU) make it platform independent and highly portable. A few lines of code in ArrayFire can replace dozens of lines of parallel computing code, saving you valuable time and lowering development costs. This crate provides Rust bindings for ArrayFire library."
version = "3.2.0"
version = "3.3.0"
documentation = "http://arrayfire.github.io/arrayfire-rust/arrayfire/index.html"
homepage = "https://github.com/arrayfire/arrayfire"
repository = "https://github.com/arrayfire/arrayfire-rust"
Expand Down
2 changes: 1 addition & 1 deletion arrayfire
Submodule arrayfire updated 459 files
6 changes: 3 additions & 3 deletions examples/helloworld.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ fn main() {
let num_rows: u64 = 5;
let num_cols: u64 = 3;
let values: &[f32] = &[1.0, 2.0, 3.0];
let indices = Array::new(Dim4::new(&[3, 1, 1, 1]), values, Aftype::F32).unwrap();
let indices = Array::new(values, Dim4::new(&[3, 1, 1, 1])).unwrap();

let dims = Dim4::new(&[num_rows, num_cols, 1, 1]);

Expand Down Expand Up @@ -74,13 +74,13 @@ fn main() {
println!("Set last row to 1's");
let r_dims = Dim4::new(&[3, 1, 1, 1]);
let r_input: [f32; 3] = [1.0, 1.0, 1.0];
let r = Array::new(r_dims, &r_input, Aftype::F32).unwrap();
let r = Array::new(&r_input, r_dims).unwrap();
print(&set_row(&a, &r, num_rows - 1).unwrap());

println!("Create 2-by-3 matrix from host data");
let d_dims = Dim4::new(&[2, 3, 1, 1]);
let d_input: [i32; 6] = [1, 2, 3, 4, 5, 6];
let d = &Array::new(d_dims, &d_input, Aftype::S32).unwrap();
let d = &Array::new(&d_input, d_dims).unwrap();
print(d);

// printf("Copy last column onto first\n");
Expand Down
9 changes: 7 additions & 2 deletions examples/pi.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#[macro_use(mem_info)]
extern crate arrayfire as af;
extern crate time;

Expand All @@ -12,11 +13,13 @@ fn main() {
let samples = 20_000_000;
let dims = Dim4::new(&[samples, 1, 1, 1]);

let x = &randu(dims, Aftype::F32).unwrap();
let y = &randu(dims, Aftype::F32).unwrap();
let x = &randu::<f32>(dims).unwrap();
let y = &randu::<f32>(dims).unwrap();

let start = PreciseTime::now();

mem_info!("Before benchmark");

for bench_iter in 0..100 {
let pi_val = add(&mul(x, x, false).unwrap(), &mul(y, y, false).unwrap(), false)
.and_then( |z| sqrt(&z) )
Expand All @@ -29,4 +32,6 @@ fn main() {
let end = PreciseTime::now();

println!("Estimated Pi Value in {} seconds", start.to(end) / 100);

mem_info!("After benchmark");
}
2 changes: 1 addition & 1 deletion examples/snow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ fn main() {
let dims = Dim4::new(&[1280, 720, 3, 1]);

loop {
randu(dims, Aftype::F32).as_ref()
randu::<f32>(dims).as_ref()
.map(|arr| wnd.draw_image(arr, None));

if wnd.is_closed().unwrap() == true { break; }
Expand Down
14 changes: 7 additions & 7 deletions examples/unified.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fn test_backend(){
let dims = Dim4::new(&[num_rows, num_cols, 1, 1]);

println!("Create a 10-by-10 matrix of random floats on the compute device");
let a = match randu(dims, Aftype::F32) {
let a = match randu::<f32>(dims) {
Ok(value) => value,
Err(error) => panic!("{}", error),
};
Expand All @@ -24,29 +24,29 @@ fn main() {
println!("There are {:?} available backends", get_backend_count().unwrap());
let available = get_available_backends().unwrap();

if available.contains(&Backend::AF_BACKEND_CPU){
if available.contains(&Backend::CPU){
println!("Evaluating CPU Backend...");
let err = set_backend(Backend::AF_BACKEND_CPU);
let err = set_backend(Backend::CPU);
println!("There are {} CPU compute devices", device_count().unwrap());
match err {
Ok(_) => test_backend(),
Err(e) => println!("CPU backend error: {}", e),
};
}

if available.contains(&Backend::AF_BACKEND_CUDA){
if available.contains(&Backend::CUDA){
println!("Evaluating CUDA Backend...");
let err = set_backend(Backend::AF_BACKEND_CUDA);
let err = set_backend(Backend::CUDA);
println!("There are {} CUDA compute devices", device_count().unwrap());
match err {
Ok(_) => test_backend(),
Err(e) => println!("CUDA backend error: {}", e),
};
}

if available.contains(&Backend::AF_BACKEND_OPENCL){
if available.contains(&Backend::OPENCL){
println!("Evaluating OpenCL Backend...");
let err = set_backend(Backend::AF_BACKEND_OPENCL);
let err = set_backend(Backend::OPENCL);
println!("There are {} OpenCL compute devices", device_count().unwrap());
match err {
Ok(_) => test_backend(),
Expand Down
117 changes: 103 additions & 14 deletions src/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ extern crate libc;

use dim4::Dim4;
use defines::{AfError, Aftype, Backend};
use util::HasAfEnum;
use self::libc::{uint8_t, c_void, c_int, c_uint, c_longlong};

type MutAfArray = *mut self::libc::c_longlong;
Expand Down Expand Up @@ -72,6 +73,21 @@ extern {
fn af_cast(out: MutAfArray, arr: AfArray, aftype: uint8_t) -> c_int;

fn af_get_backend_id(backend: *mut c_int, input: AfArray) -> c_int;

fn af_get_device_id(device: *mut c_int, input: AfArray) -> c_int;

fn af_create_strided_array(arr: MutAfArray, data: *const c_void, offset: DimT,
ndims: c_uint, dims: *const DimT, strides: *const DimT,
aftype: uint8_t) -> c_int;

fn af_get_strides(s0: *mut DimT, s1: *mut DimT, s2: *mut DimT, s3: *mut DimT,
arr: AfArray) -> c_int;

fn af_get_offset(offset: *mut DimT, arr: AfArray) -> c_int;

fn af_is_linear(result: *mut c_int, arr: AfArray) -> c_int;

fn af_is_owner(result: *mut c_int, arr: AfArray) -> c_int;
}

/// A multidimensional data container
Expand Down Expand Up @@ -104,11 +120,12 @@ impl Array {
///
/// ```
/// let values: &[f32] = &[1.0, 2.0, 3.0];
/// let indices = Array::new(Dim4::new(&[3, 1, 1, 1]), values, Aftype::F32).unwrap();
/// let indices = Array::new(values, Dim4::new(&[3, 1, 1, 1])).unwrap();
/// ```
#[allow(unused_mut)]
pub fn new<T>(dims: Dim4, slice: &[T], aftype: Aftype) -> Result<Array, AfError> {
pub fn new<T: HasAfEnum>(slice: &[T], dims: Dim4) -> Result<Array, AfError> {
unsafe {
let aftype = T::get_af_dtype();
let mut temp: i64 = 0;
let err_val = af_create_array(&mut temp as MutAfArray,
slice.as_ptr() as *const c_void,
Expand All @@ -122,21 +139,61 @@ impl Array {
}
}

/// Constructs a new Array object from strided data
///
/// The data pointed by the slice passed to this function can possibily be offseted using an additional `offset` parameter.
#[allow(unused_mut)]
pub fn new_strided<T: HasAfEnum>(slice: &[T], offset: i64,
dims: Dim4, strides: Dim4) -> Result<Array, AfError> {
unsafe {
let aftype = T::get_af_dtype();
let mut temp: i64 = 0;
let err_val = af_create_strided_array(&mut temp as MutAfArray,
slice.as_ptr() as *const c_void,
offset as DimT,
dims.ndims() as c_uint,
dims.get().as_ptr() as * const c_longlong,
strides.get().as_ptr() as * const c_longlong,
aftype as uint8_t);
match err_val {
0 => Ok(Array {handle: temp}),
_ => Err(AfError::from(err_val)),
}
}
}

/// Returns the backend of the Array
///
/// # Return Values
///
/// Returns an value of type `Backend` which indicates which backend
/// was active when Array was created.
pub fn get_backend(&self) -> Backend {
pub fn get_backend(&self) -> Result<Backend, AfError> {
unsafe {
let mut ret_val: i32 = 0;
af_get_backend_id(&mut ret_val as *mut c_int, self.handle as AfArray);
match ret_val {
1 => Backend::AF_BACKEND_CPU,
2 => Backend::AF_BACKEND_CUDA,
3 => Backend::AF_BACKEND_OPENCL,
_ => Backend::AF_BACKEND_DEFAULT,
let err_val = af_get_backend_id(&mut ret_val as *mut c_int, self.handle as AfArray);
match (err_val, ret_val) {
(0, 1) => Ok(Backend::CPU),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good way to squash the error check in. 👍

(0, 2) => Ok(Backend::CUDA),
(0, 3) => Ok(Backend::OPENCL),
_ => Err(AfError::from(err_val)),
}
}
}

/// Returns the device identifier(integer) on which the Array was created
///
/// # Return Values
///
/// Return the device id on which Array was created.
pub fn get_device_id(&self) -> Result<i32, AfError> {
unsafe {
let mut ret_val: i32 = 0;
let err_val = af_get_device_id(&mut ret_val as *mut c_int, self.handle as AfArray);
match err_val {
0 => Ok(ret_val),
_ => Err(AfError::from(err_val)),

}
}
}
Expand Down Expand Up @@ -172,8 +229,8 @@ impl Array {
let mut ret1: i64 = 0;
let mut ret2: i64 = 0;
let mut ret3: i64 = 0;
let err_val = af_get_dims(&mut ret0 as *mut c_longlong, &mut ret1 as *mut c_longlong,
&mut ret2 as *mut c_longlong, &mut ret3 as *mut c_longlong,
let err_val = af_get_dims(&mut ret0 as *mut DimT, &mut ret1 as *mut DimT,
&mut ret2 as *mut DimT, &mut ret3 as *mut DimT,
self.handle as AfArray);
match err_val {
0 => Ok(Dim4::new(&[ret0 as u64, ret1 as u64, ret2 as u64, ret3 as u64])),
Expand All @@ -182,6 +239,23 @@ impl Array {
}
}

/// Returns the strides of the Array
pub fn strides(&self) -> Result<Dim4, AfError> {
unsafe {
let mut ret0: i64 = 0;
let mut ret1: i64 = 0;
let mut ret2: i64 = 0;
let mut ret3: i64 = 0;
let err_val = af_get_strides(&mut ret0 as *mut DimT, &mut ret1 as *mut DimT,
&mut ret2 as *mut DimT, &mut ret3 as *mut DimT,
self.handle as AfArray);
match err_val {
0 => Ok(Dim4::new(&[ret0 as u64, ret1 as u64, ret2 as u64, ret3 as u64])),
_ => Err(AfError::from(err_val)),
}
}
}

/// Returns the number of dimensions of the Array
pub fn numdims(&self) -> Result<u32, AfError> {
unsafe {
Expand All @@ -194,6 +268,18 @@ impl Array {
}
}

/// Returns the offset to the pointer from where data begins
pub fn offset(&self) -> Result<i64, AfError> {
unsafe {
let mut ret_val: i64 = 0;
let err_val = af_get_offset(&mut ret_val as *mut DimT, self.handle as AfArray);
match err_val {
0 => Ok(ret_val),
_ => Err(AfError::from(err_val)),
}
}
}

/// Returns the native FFI handle for Rust object `Array`
pub fn get(&self) -> i64 {
self.handle
Expand Down Expand Up @@ -247,12 +333,15 @@ impl Array {
is_func!(is_floating, af_is_floating);
is_func!(is_integer, af_is_integer);
is_func!(is_bool, af_is_bool);
is_func!(is_linear, af_is_linear);
is_func!(is_owner, af_is_owner);

/// Cast the Array data type to `target_type`
pub fn cast(&self, target_type: Aftype) -> Result<Array, AfError> {
pub fn cast<T: HasAfEnum>(&self) -> Result<Array, AfError> {
unsafe {
let trgt_type = T::get_af_dtype();
let mut temp: i64 = 0;
let err_val = af_cast(&mut temp as MutAfArray, self.handle as AfArray, target_type as uint8_t);
let err_val = af_cast(&mut temp as MutAfArray, self.handle as AfArray, trgt_type as uint8_t);
match err_val {
0 => Ok(Array::from(temp)),
_ => Err(AfError::from(err_val)),
Expand Down Expand Up @@ -301,7 +390,7 @@ impl Drop for Array {
///
/// ```
/// println!("Create a 5-by-3 matrix of random floats on the GPU");
/// let a = match randu(dims, Aftype::F32) {
/// let a = match randu::<f32>(dims) {
/// Ok(value) => value,
/// Err(error) => panic!("{}", error),
/// };
Expand Down
23 changes: 20 additions & 3 deletions src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ extern {
fn af_set_backend(bknd: uint8_t) -> c_int;
fn af_get_backend_count(num_backends: *mut c_uint) -> c_int;
fn af_get_available_backends(backends: *mut c_int) -> c_int;
fn af_get_active_backend(backend: *mut c_int) -> c_int;
}

/// Toggle backends between cuda, opencl or cpu
Expand Down Expand Up @@ -47,12 +48,28 @@ pub fn get_available_backends() -> Result<Vec<Backend>, AfError> {
match err_val {
0 => {
let mut b = Vec::new();
if temp & 0b0100 == 0b0100 { b.push(Backend::AF_BACKEND_OPENCL); }
if temp & 0b0010 == 0b0010 { b.push(Backend::AF_BACKEND_CUDA); }
if temp & 0b0001 == 0b0001 { b.push(Backend::AF_BACKEND_CPU); }
if temp & 0b0100 == 0b0100 { b.push(Backend::OPENCL); }
if temp & 0b0010 == 0b0010 { b.push(Backend::CUDA); }
if temp & 0b0001 == 0b0001 { b.push(Backend::CPU); }
Ok(b)
},
_ => Err(AfError::from(err_val)),
}
}
}

/// Get current active backend
#[allow(unused_mut)]
pub fn get_active_backend() -> Result<Backend, AfError> {
unsafe {
let mut temp: i32 = 0;
let err_val = af_get_active_backend(&mut temp as *mut c_int);
match (err_val, temp) {
(0, 0) => Ok(Backend::DEFAULT),
(0, 1) => Ok(Backend::CPU),
(0, 2) => Ok(Backend::CUDA),
(0, 4) => Ok(Backend::OPENCL),
_ => Err(AfError::from(err_val)),
}
}
}
Loading