FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
llama.cpp/tools/server/server-queue.h at master · rioscode/llama.cpp · GitHub
rioscode
/
llama.cpp
Public
forked from
ggml-org/llama.cpp
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Pull requests
0
Actions
Projects
Security and quality
0
Insights
Additional navigation options
Code
Pull requests
Actions
Projects
Security and quality
Insights
Expand file tree
Breadcrumbs
llama.cpp
/
tools
/
server
/
server-queue.h
Copy path
More file actions
More file actions
Latest commit
History
History
History
244 lines (196 loc) · 9.06 KB
Breadcrumbs
llama.cpp
/
tools
/
server
/
server-queue.h
Copy path
File metadata and controls
244 lines (196 loc) · 9.06 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
#
pragma
once
#
include
"
server-task.h
"
#
include
<
condition_variable
>
#
include
<
deque
>
#
include
<
exception
>
#
include
<
mutex
>
#
include
<
thread
>
#
include
<
vector
>
#
include
<
unordered_set
>
//
struct for managing server tasks
//
in most cases, use server_response_reader to post new tasks and retrieve results
struct
server_queue
{
private:
int
id =
0
;
bool
running =
false
;
bool
sleeping =
false
;
bool
req_stop_sleeping =
false
;
int64_t
time_last_task =
0
;
//
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 a yield starts
std::exception_ptr exception;
//
exception thrown while processing tasks, if any
bool
stop =
false
;
bool
busy =
false
;
//
set by yield_to_queue(), cleared by the worker once it is done processing tasks
bool
yielding =
false
;
//
work() is still running on the start_loop() thread
};
worker_t
worker;
//
callback functions
std::function<
bool
(server_task &&,
bool
)> callback_new_task;
std::function<
void
(
void
)> callback_update_slots;
std::vector<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
);
//
multi-task version of post()
int
post
(std::vector<server_task> && tasks,
bool
front =
false
);
//
Add a new task, but defer until one slot is available
void
defer
(server_task && task);
//
Get the next id for creating a new task
int
get_new_id
();
//
Call when the state of one slot is changed, it will move one task from deferred to main queue
//
prioritize tasks that use the specified slot (otherwise, pop the first deferred task)
void
pop_deferred_task
(
int
id_slot);
//
if sleeping, request exiting sleep state and wait until it is done
//
returns immediately if not sleeping
void
wait_until_no_sleep
();
bool
is_sleeping
() {
std::unique_lock<std::mutex>
lock
(mutex_tasks);
return
sleeping;
}
//
end the start_loop routine
void
terminate
();
/*
*
* Main loop consists of these steps:
* - Wait until a new task arrives
* - Process the task (i.e. maybe copy data into slot)
* - Check if multitask is finished
* - Update all slots
*
* Sleeping procedure (disabled if idle_sleep_ms < 0):
* - If there is no task after idle_sleep_ms, enter sleeping state
* note: metrics tasks are processed as usual, but do not reset the idle timer
* - Call callback_sleeping_state(true)
* - Wait until req_stop_sleeping is set to true
* - Call callback_sleeping_state(false)
* - Exit sleeping state
*/
void
start_loop
(
int64_t
idle_sleep_ms = -
1
);
//
while waiting for work() to finish, run process_new_tasks on the worker thread
//
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);
return
queue_tasks_deferred.
size
();
}
//
//
Functions below are not thread-safe, must only be used before start_loop() is called
//
//
Register function to process a new task
//
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
//
note: while yielding, the callback runs on worker thread, not main thread
void
on_new_task
(std::function<
bool
(server_task &&,
bool
)> callback) {
callback_new_task =
std::move
(callback);
}
//
Register the function to be called when all slots data is ready to be processed
void
on_update_slots
(std::function<
void
(
void
)> callback) {
callback_update_slots =
std::move
(callback);
}
//
Register callback for sleeping state change; multiple callbacks are allowed
//
for example: register order cb0, cb1, cb2
//
entering sleep: queue.sleeping = true --> cb0(true) --> cb1(true) --> cb2(true)
//
leaving sleep: cb2(false) --> cb1(false) --> cb0(false) --> queue.sleeping = false
//
note: caller will hold mutex_tasks while calling the callbacks
void
on_sleeping_state
(std::function<
void
(
bool
)> callback) {
callback_sleeping_state.
push_back
(
std::move
(callback));
}
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
//
in most cases, use server_response_reader to retrieve results
struct
server_response
{
private:
bool
running =
true
;
//
for keeping track of all tasks waiting for the result
std::unordered_set<
int
> waiting_task_ids;
//
the main result queue (using ptr for polymorphism)
std::vector<server_task_result_ptr> queue_results;
std::mutex mutex_results;
std::condition_variable condition_results;
public:
//
add the id_task to the list of tasks waiting for response
void
add_waiting_task_id
(
int
id_task);
void
add_waiting_task_ids
(
const
std::unordered_set<
int
> & id_tasks);
//
when the request is finished, we can remove task associated with it
void
remove_waiting_task_id
(
int
id_task);
//
remove multiple tasks from waiting list
void
remove_waiting_task_ids
(
const
std::unordered_set<
int
> & id_tasks);
//
This function blocks the thread until there is a response for one of the id_tasks
server_task_result_ptr
recv
(
const
std::unordered_set<
int
> & id_tasks);
//
same as recv(), but have timeout in seconds
//
if timeout is reached, nullptr is returned
server_task_result_ptr
recv_with_timeout
(
const
std::unordered_set<
int
> & id_tasks,
int
timeout);
//
single-task version of recv()
server_task_result_ptr
recv
(
int
id_task);
//
Send a new result to a waiting id_task
void
send
(server_task_result_ptr && result);
//
broadcast a new result to all waiting tasks
//
(used by router mode)
void
broadcast
(server_task_result_ptr && result);
//
terminate the waiting loop
void
terminate
();
};
//
RAII wrapper to make working with server_queue and server_response easier
//
it provides a generator-like API for server responses
//
support pooling connection state and aggregating multiple results
struct
server_response_reader
{
std::unordered_set<
int
> id_tasks;
server_queue & queue_tasks;
server_response & queue_results;
size_t
received_count =
0
;
bool
cancelled =
false
;
int
polling_interval_seconds;
//
tracking generation state and partial tool calls
//
only used by streaming completions
std::vector<task_result_state> states;
//
should_stop function will be called each polling_interval_seconds
server_response_reader
(server_queue & queue_tasks, server_response & queue_results,
int
polling_interval_seconds)
: queue_tasks(queue_tasks), queue_results(queue_results), polling_interval_seconds(polling_interval_seconds) {}
~server_response_reader
() {
stop
();
}
int
get_new_id
() {
return
queue_tasks.
get_new_id
();
}
//
if front = true, the task will be posted to the front of the queue (high priority)
void
post_task
(server_task && task,
bool
front =
false
);
void
post_tasks
(std::vector<server_task> && tasks,
bool
front =
false
);
bool
has_next
()
const
;
//
return nullptr if should_stop() is true before receiving a result
//
note: if one error is received, it will stop further processing and return error result
server_task_result_ptr
next
(
const
std::function<
bool
()> & should_stop);
struct
batch_response
{
bool
is_terminated =
false
;
//
if true, indicates that processing was stopped before all results were received
std::vector<server_task_result_ptr> results;
server_task_result_ptr error;
//
nullptr if no error
};
//
aggregate multiple results
batch_response
wait_for_all
(
const
std::function<
bool
()> & should_stop);
void
stop
();
};
Back
|
FazBrowse Home
|
New Git URL