making code thread safe
play

Making code thread-safe Kyle J. Knoepfel 25 June 2019 LArSoft - PowerPoint PPT Presentation

Making code thread-safe Kyle J. Knoepfel 25 June 2019 LArSoft Workshop 2019 So youre going to make your code thread-safe 2 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019 So youre going to make your code thread-safe The


  1. Making code thread-safe Kyle J. Knoepfel 25 June 2019 LArSoft Workshop 2019

  2. So you’re going to make your code thread-safe… 2 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  3. So you’re going to make your code thread-safe… • The difficulty of this task depends on the context 3 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  4. So you’re going to make your code thread-safe… • The difficulty of this task depends on the context • What language are you using? – Multi-threading in (e.g.) C++ is harder – Multi-threading in (e.g.) Go, Rust, Haskell is easier • Are you starting from scratch or retrofitting code? • Does it make sense for the code in question to be multi-threaded? 4 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  5. So you’re going to make your code thread-safe… • The difficulty of this task depends on the context • What language are you using? – Multi-threading in (e.g.) C++ is harder – Multi-threading in (e.g.) Go, Rust, Haskell is easier • Are you starting from scratch or retrofitting code? • Does it make sense for the code in question to be multi-threaded? When writing multi-threaded code, you should always ask: What’s the context in which this function will be called? 5 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  6. Thread-safety matrix 6 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  7. Thread-safety matrix Is the object shared across threads? Yes No 7 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  8. Thread-safety matrix Is the object shared across threads? Yes No Yes Is the object mutable? No 8 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  9. Thread-safety matrix Is the object shared across threads? Yes No Data races possible OK Yes Is the object mutable? OK OK No 9 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  10. Thread-safety matrix Is the object shared across threads? Yes No Synchronous Asynchronous access access OK OK Data races Yes guaranteed Is the object mutable? OK OK No 10 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  11. Thread-safety matrix Is the object shared across threads? Yes No Synchronous Asynchronous access access OK OK Data races Yes guaranteed Is the object mutable? OK OK No You must get out of that box! 11 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  12. Thread-safety matrix Is the object shared across threads? Yes No Synchronous Asynchronous access access Sometimes the easiest solution. OK Data races Yes Requires more memory. guaranteed Is the object mutable? OK OK No 12 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  13. Thread-safety matrix Is the object shared across threads? Yes No Synchronous Asynchronous access access Sometimes the easiest solution. OK Data races Yes Requires more memory. guaranteed Is the object mutable? OK No Memory savings. Can be difficult to make things immutable. 13 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  14. Thread-safety matrix Is the object shared across threads? Yes No Synchronous Asynchronous access access Sometimes the easiest solution. Data races Awkward. Yes Requires more memory. Will not discuss. guaranteed Is the object mutable? OK No Memory savings. Can be difficult to make things immutable. 14 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  15. Thread-safety matrix Is the object shared across threads? Yes No Synchronous Asynchronous access access Sometimes the easiest solution. Data races Awkward. Yes Requires more memory. Will not discuss. guaranteed Is the object mutable? OK No Memory savings. Can be difficult to make things immutable. Making your code thread-safe often requires a combination of methods. 15 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  16. To make your code thread-safe… • You must know what is shared among threads, and the contexts in which the sharing happens. 16 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  17. To make your code thread-safe… • You must know what is shared among threads, and the contexts in which the sharing happens. • Game – Part 1 – Thread-safety and free-functions • Game – Part 2 – Thread-safety and class member functions 17 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  18. Part 1: Is it thread-safe? The pattern we’ll follow void test(...) { // ... } int main() { execute_with_10_threads(test, ...); } 18 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  19. Part 1: Is it thread-safe? void test() {} int main() { execute_with_10_threads(test); } 19 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  20. Part 1: Is it thread-safe? void test() {} Yes int main() { execute_with_10_threads(test); } 20 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  21. Part 1: Is it thread-safe? void test() { auto i = 42; } int main() { execute_with_10_threads(test); } 21 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  22. Part 1: Is it thread-safe? void test() { auto i = 42; Yes } Each thread gets its int main() own stack memory. { execute_with_10_threads(test); } 22 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  23. Part 1: Is it thread-safe? void test(int j) { ++j; } int main() { auto i = 42; execute_with_10_threads(test, i); } 23 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  24. Part 1: Is it thread-safe? void test(int j) { ++j; } Yes The value 42 is int main() copied into j for { each thread. auto i = 42; execute_with_10_threads(test, i); } 24 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  25. Part 1: Is it thread-safe? void test() { static int j{0}; ++j; } int main() { execute_with_10_threads(test); } 25 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  26. Part 1: Is it thread-safe? void test() { static int j{0}; ++j; No } j is shared across all threads that call test int main() { operator++ requires a read and then write execute_with_10_threads(test); } 26 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  27. Part 1: Is it thread-safe? void test() { static int j{0}; int k = j; ++k; } int main() { execute_with_10_threads(test); } 27 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  28. Part 1: Is it thread-safe? void test() { static int j{0}; int k = j; Yes ++k; Although j is shared, its } value never changes k is a stack variable. int main() { This is fragile, though! execute_with_10_threads(test); } 28 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  29. Part 1: Is it thread-safe? void test() { static int j{0}; int& k = j; ++k; } int main() { execute_with_10_threads(test); } 29 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  30. Part 1: Is it thread-safe? void test() { static int j{0}; int& k = j; No ++k; k now refers to } a shared object! int main() operator++ requires a read and then write { execute_with_10_threads(test); } 30 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  31. Part 1: Is it thread-safe? void test() { static int j{0}; int& k = j; No ++k; k now refers to } One character can break a program. a shared object! int main() operator++ requires a read and then write { execute_with_10_threads(test); } 31 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  32. Part 1: Is it thread-safe? void test(std::string const& sentence) { auto pos = sentence.find("C++17"); } int main() { std::string sentence{"I love C++17."}; execute_with_10_threads(test, sentence); } 32 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  33. Part 1: Is it thread-safe? void test(std::string const& sentence) Yes { auto pos = sentence.find("C++17"); In general, calling const-qualified } C++ STL member functions is int main() thread-safe… { assuming std::string sentence{"I love C++17."}; another thread execute_with_10_threads(test, sentence); isn’t adjusting } the object. 33 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  34. Part 1: Is it thread-safe? void test() { MyArbitraryType t; } int main() { execute_with_10_threads(test); } 34 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  35. Part 1: Is it thread-safe? void test() { MyArbitraryType t; } It depends int main() { execute_with_10_threads(test); } 35 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  36. Part 1: Is it thread-safe? void test() using MyArbitraryType = int; { MyArbitraryType t; } int main() { execute_with_10_threads(test); } 36 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  37. Part 1: Is it thread-safe? void test() using MyArbitraryType = int; { MyArbitraryType t; } Yes int main() { execute_with_10_threads(test); } 37 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  38. Part 1: Is it thread-safe? void test() struct MyArbitraryType { { MyArbitraryType() MyArbitraryType t; { } static int counter; ++counter; int main() } { }; execute_with_10_threads(test); } 38 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

  39. Part 1: Is it thread-safe? void test() struct MyArbitraryType { { MyArbitraryType() MyArbitraryType t; { } static int counter; ++counter; int main() } { }; execute_with_10_threads(test); No } Although there is one ‘t’ per thread, the constructor accesses shared memory. 39 6/25/19 Kyle J. Knoepfel | LArSoft Workshop 2019

Recommend


More recommend