server: allow accessing /metrics and /slots during llama_decode() (#27041)
* server_queue::worker * call llama_decode inside yield_to_queue * also handle process_mtmd_chunk * clean up * nits * rm test
This commit is contained in:
@@ -4,7 +4,9 @@
|
||||
|
||||
#include <condition_variable>
|
||||
#include <deque>
|
||||
#include <exception>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#include <unordered_set>
|
||||
|
||||
@@ -21,16 +23,32 @@ private:
|
||||
// queues
|
||||
std::deque<server_task> queue_tasks;
|
||||
std::deque<server_task> queue_tasks_deferred;
|
||||
// tasks declined while yielding, put back in queue_tasks once the yield is done
|
||||
// note: kept as a member so that cleanup_pending_task() can also reach them
|
||||
std::deque<server_task> queue_tasks_unhandled;
|
||||
|
||||
std::mutex mutex_tasks;
|
||||
std::condition_variable condition_tasks;
|
||||
|
||||
// used by yield_to_queue, all fields are guarded by mutex_tasks
|
||||
struct worker_t {
|
||||
std::thread thread;
|
||||
std::condition_variable cv; // the worker sleeps on this until there is work
|
||||
std::function<void()> work; // pending work, picked up by the thread
|
||||
std::exception_ptr exception; // exception thrown by work(), if any
|
||||
bool stop = false;
|
||||
bool busy = false;
|
||||
};
|
||||
worker_t worker;
|
||||
|
||||
// callback functions
|
||||
std::function<void(server_task &&)> callback_new_task;
|
||||
std::function<void(void)> callback_update_slots;
|
||||
std::function<void(bool)> callback_sleeping_state;
|
||||
std::function<bool(server_task &&, bool)> callback_new_task;
|
||||
std::function<void(void)> callback_update_slots;
|
||||
std::function<void(bool)> callback_sleeping_state;
|
||||
|
||||
public:
|
||||
~server_queue() { worker_stop(); }
|
||||
|
||||
// Add a new task to the end of the queue
|
||||
int post(server_task && task, bool front = false);
|
||||
|
||||
@@ -75,6 +93,15 @@ public:
|
||||
*/
|
||||
void start_loop(int64_t idle_sleep_ms = -1);
|
||||
|
||||
// run work() on a separate thread, while the current thread calls process_new_tasks
|
||||
// returns once work() is done (may throw exceptions)
|
||||
// must be called from start_loop() thread (ideally inside callback_update_slots)
|
||||
// use case: return metrics while encode/decode is running
|
||||
// ref: https://github.com/ggml-org/llama.cpp/pull/27041
|
||||
//
|
||||
// tasks declined by callback_new_task are put back in the queue once this returns
|
||||
void yield_to_queue(std::function<void()> && work);
|
||||
|
||||
// for metrics
|
||||
size_t queue_tasks_deferred_size() {
|
||||
std::unique_lock<std::mutex> lock(mutex_tasks);
|
||||
@@ -86,7 +113,10 @@ public:
|
||||
//
|
||||
|
||||
// Register function to process a new task
|
||||
void on_new_task(std::function<void(server_task &&)> callback) {
|
||||
// the second argument tells whether the queue is currently yielding (see yield_to_queue)
|
||||
// only then may the callback return false to decline the task, and it must leave it
|
||||
// untouched, so that it can be put back in the queue later
|
||||
void on_new_task(std::function<bool(server_task &&, bool)> callback) {
|
||||
callback_new_task = std::move(callback);
|
||||
}
|
||||
|
||||
@@ -112,6 +142,15 @@ public:
|
||||
|
||||
private:
|
||||
void cleanup_pending_task(int id_target);
|
||||
|
||||
// process all pending tasks in the queue
|
||||
// returns true if the queue is terminated, false if there is no more task to process
|
||||
// while yielding, declined tasks are moved to queue_tasks_unhandled
|
||||
bool process_new_tasks(bool is_yielding);
|
||||
|
||||
// for worker_t
|
||||
void worker_loop();
|
||||
void worker_stop();
|
||||
};
|
||||
|
||||
// struct for managing server responses
|
||||
|
||||
Reference in New Issue
Block a user