Skip to content
Open
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
19 changes: 17 additions & 2 deletions src/cpu/backend.cc
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,24 @@ namespace ctranslate2 {
}

#ifdef CT2_WITH_RUY
// The per-thread ruy::Context is heap-allocated so that its lifetime is not tied
// to thread-local destruction. Its destructor joins ruy's internal thread pool;
// on Windows that join, if it runs while the owning thread is exiting (under the
// loader lock), deadlocks ThreadPool shutdown (jkawamoto/ctranslate2-rs#64).
// Instead we destroy it explicitly via clear_ruy_context() from ReplicaWorker::
// finalize(), which runs on the worker thread in a normal context (not thread
// exit), so the join completes and no memory (incl. ruy's prepacked cache) leaks.
static thread_local ruy::Context* ruy_context = nullptr;

ruy::Context *get_ruy_context() {
static thread_local ruy::Context context;
return &context;
if (!ruy_context)
ruy_context = new ruy::Context();
return ruy_context;
}

void clear_ruy_context() {
delete ruy_context;
ruy_context = nullptr;
}
#endif
}
Expand Down
3 changes: 3 additions & 0 deletions src/cpu/backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ namespace ctranslate2 {
bool pack_gemm_weights(ComputeType compute_type);
#ifdef CT2_WITH_RUY
ruy::Context *get_ruy_context();
// Destroy the calling thread's ruy::Context (joins ruy's thread pool). Must be
// called from a normal execution context, not during thread exit — see backend.cc.
void clear_ruy_context();
#endif

}
Expand Down
14 changes: 12 additions & 2 deletions src/devices.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
# include "cuda/utils.h"
# include "cuda/random.h"
#endif
#ifdef CT2_WITH_RUY
# include "cpu/backend.h"
#endif
#ifdef CT2_WITH_TENSOR_PARALLEL
# include <unistd.h>
#endif
Expand Down Expand Up @@ -125,9 +128,16 @@ namespace ctranslate2 {
if (device == Device::CUDA) {
cuda::free_curand_states();
}
#else
(void)device;
#endif
#ifdef CT2_WITH_RUY
if (device == Device::CPU) {
// Release this worker thread's ruy::Context here (a normal execution
// context) rather than at thread exit, where joining ruy's internal
// threads deadlocks ThreadPool shutdown on Windows (ctranslate2-rs#64).
cpu::clear_ruy_context();
}
#endif
(void)device;
}

// Initialize the static member variable
Expand Down
Loading