-
Notifications
You must be signed in to change notification settings - Fork 30
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
dlib is not thread safe #25
Comments
Hello there! Thanks for bringing this up :D |
I am running the face detector and landmark predictor inside of rayon. This is the code (without rayon), it breaks if you do This is the code that calls into dlib: Using gdb I find the crash on the memory allocator from dlib (C++):
It is flaky (seems to work about every other time). You can run it like |
I am running it on |
Hello! Sorry for the late reply, i took some time to try and understand your code and what you wanted to achieve. Please do correct me if i`m wrong, but i guess you wanted to use rayon to find rectangles in multiple images in an asynchronous way. If that's correct, i believe there may be some mistake in your code sample. I did a small reproducible code to test this:
This works without any errors, proving that the structs in this crate are indeed thread-safe (at least, with this code approach). I really hope to have been able to help or guess your code objective correctly. Please do try this out, and keep us informed! |
That is basically what I do, with a few minor tweaks:
So your code would look like this (might not compile, I haven't tested it): use dlib_face_recognition::{FaceDetector, FaceDetectorTrait, ImageMatrix, LandmarkPredictor, LandmarkPredictorTrait};
use rayon::prelude::*;
use serde::{Deserialize, Serialize};
use std::{collections::HashMap, fs::read_dir};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SerializableRectangle {
pub left: i64,
pub top: i64,
pub right: i64,
pub bottom: i64,
}
fn find_rectangles(image: &String, detector: &FaceDetector, predictor: &LandmarkPredictor) -> Vec<SerializableRectangle> {
println!("{image}");
let mut rect_results: Vec<SerializableRectangle> = vec![];
let image = image::open(image).unwrap().to_rgb8();
let matrix = ImageMatrix::from_image(&image);
let face_locations = detector.face_locations(&matrix);
for found_rectangle in face_locations.iter() {
let serializable_rectangle = SerializableRectangle {
left: found_rectangle.left,
right: found_rectangle.right,
top: found_rectangle.top,
bottom: found_rectangle.bottom,
};
rect_results.push(serializable_rectangle);
// Also save the facial landmarks here
}
rect_results
}
fn main() {
let Ok(paths) = read_dir("./images") else {
panic!("Unable to read images folder!")
};
let mut images: HashMap<String, Vec<SerializableRectangle>> = HashMap::new();
for path in paths.flatten() {
let string = path.path().display().to_string();
images.insert(string, vec![]);
}
let detector = FaceDetector::default();
let predictor = LandmarkPredictor::new("/path/to/model");
images.par_iter_mut().for_each(|entry| {
let rects = find_rectangles(entry.0, &detector, &predictor);
for rect in rects {
entry.1.push(rect);
}
});
for entry in images {
println!("{:?}", entry.1)
}
} |
I'll try to write a minimal example next weekend when I have time |
Hello! The problem is: negative impls are a nightly locked feature of the language, meaning we cannot do this PR and still use this crate in a stable Rust compiler toolchain. This would also force whatever projects are using this crate to also be forced to run Nightly Rust. The negative impls RFC is here: rust-lang/rust#68318. The code/PR itself is pretty easy by itself, so not a problem except that. Ultimately, the decision should be by @kerryeon. |
You can work around that limitation by adding some phantom data to them (specifically !Sync/!Send phantom data, like UnsafeCell) If I remember correctly |
The right choice should be adding a field with I don't know how the dlib types work, if they have interior mutability, they should be Having them be |
Just did some code testing, PhantomData solution seems to work, albeit a little jank, but it avoids the nightly problem. Thanks for all the info and cooperation! |
Hi, I read the issue and confirmed that And it seems that both |
fix(#25): Mark certain structs as !Sync
Trying to speed up predictions by using
rayon
causes a core dump within dlib's allocator, some of the structures should be marked as either!Sync
or!Send
(or both).The text was updated successfully, but these errors were encountered: