Concurrent device listing
michaelmattig opened this issue · comments
I'm facing the issue that concurrent access of the available OpenCL devices fails. While one call gets the correct device, a parallel call gets shown no devices at all.
If I run the following tests in parallel:
#[cfg(test)]
mod tests {
use super::*;
use ocl::{Platform, Device};
use std::{thread, time};
fn ocl(){
let platform = Platform::default();
println!("Platform:{:?}", platform);
println!("Devices:{:?}", Device::list_all(platform));
let device = Device::first(platform).unwrap();
println!("Device:{:?}", device);
}
#[test]
fn test1() {
ocl()
}
#[test]
fn test2() {
// thread::sleep(time::Duration::from_secs(1));
ocl()
}
}
most of the time only one test succeeds and yields
Platform:Platform(PlatformId(0x7fc3ffff7020))
Devices:Ok([Device(DeviceId(0x7fc400001040))])
Device:Device(DeviceId(0x7fc400001040))
while the other one shows:
Platform:Platform(PlatformId(0x7fc3ffff7020))
Devices:Ok([])called
Result::unwrap()
on anErr
value:################################ OPENCL ERROR ###############################
Error executing function: clGetDeviceIDs
Status error code: CL_DEVICE_NOT_FOUND (-1)
Executing only one test or adding a sleep before the first one, both tests succeed.
As a temporary workaround you can also force the tests to run concurrently with cargo test -- --test-threads 1
As a temporary workaround you can also force the tests to run concurrently with
cargo test -- --test-threads 1
sure, but I actually need to compile and run kernels in parallel in my application.
As a temporary workaround you can also force the tests to run concurrently with
cargo test -- --test-threads 1
sure, but I actually need to compile and run kernels in parallel in my application.
Maybe you could use a global Mutex
lock to synchronize things? This seems like an issue with the underlying OpenCL driver rather than the bindings, which makes it hard to fix.
I will use a static reference to the device for now (see code below). I would very much like to see this issue fixed though, as thread-safety is stated to be a major goal of this crate.
#[cfg(test)]
mod tests {
use super::*;
use ocl::{Platform, Device};
use lazy_static::lazy_static;
lazy_static! {
static ref DEVICE: Device = Device::first(Platform::default()).expect("Device has to exist");
}
fn ocl(){
let platform = Platform::default();
println!("Platform:{:?}", platform);
let device = *DEVICE;
println!("Device{:?}", device);
}
#[test]
fn test1() {
ocl()
}
#[test]
fn test2() {
ocl()
}
}
I don't think this is an issue with this library though - all the OpenCL calls involved in this example are supposed to be thread safe at the driver level; if the driver is breaking its own safety guarantees that's a problem with the driver.