mirror of
https://github.com/ggerganov/llama.cpp.git
synced 2024-12-26 06:10:29 +01:00
llama : fix time complexity of string replacement (#9163)
This change fixes a bug where replacing text in a very long string could cause llama.cpp to hang indefinitely. This is because the algorithm used was quadratic, due to memmove() when s.replace() is called in a loop. It seems most search results and LLM responses actually provide the O(n**2) algorithm, which is a great tragedy. Using a builder string fixes things
This commit is contained in:
parent
93bc3839f9
commit
436787f170
@ -1861,13 +1861,19 @@ std::string string_get_sortable_timestamp() {
|
|||||||
|
|
||||||
void string_replace_all(std::string & s, const std::string & search, const std::string & replace) {
|
void string_replace_all(std::string & s, const std::string & search, const std::string & replace) {
|
||||||
if (search.empty()) {
|
if (search.empty()) {
|
||||||
return; // Avoid infinite loop if 'search' is an empty string
|
return;
|
||||||
}
|
}
|
||||||
|
std::string builder;
|
||||||
|
builder.reserve(s.length());
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
while ((pos = s.find(search, pos)) != std::string::npos) {
|
size_t last_pos = 0;
|
||||||
s.replace(pos, search.length(), replace);
|
while ((pos = s.find(search, last_pos)) != std::string::npos) {
|
||||||
pos += replace.length();
|
builder.append(s, last_pos, pos - last_pos);
|
||||||
|
builder.append(replace);
|
||||||
|
last_pos = pos + search.length();
|
||||||
}
|
}
|
||||||
|
builder.append(s, last_pos, std::string::npos);
|
||||||
|
s = std::move(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
void string_process_escapes(std::string & input) {
|
void string_process_escapes(std::string & input) {
|
||||||
|
@ -216,13 +216,19 @@ static std::string gguf_data_to_str(enum gguf_type type, const void * data, int
|
|||||||
|
|
||||||
static void replace_all(std::string & s, const std::string & search, const std::string & replace) {
|
static void replace_all(std::string & s, const std::string & search, const std::string & replace) {
|
||||||
if (search.empty()) {
|
if (search.empty()) {
|
||||||
return; // Avoid infinite loop if 'search' is an empty string
|
return;
|
||||||
}
|
}
|
||||||
|
std::string builder;
|
||||||
|
builder.reserve(s.length());
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
while ((pos = s.find(search, pos)) != std::string::npos) {
|
size_t last_pos = 0;
|
||||||
s.replace(pos, search.length(), replace);
|
while ((pos = s.find(search, last_pos)) != std::string::npos) {
|
||||||
pos += replace.length();
|
builder.append(s, last_pos, pos - last_pos);
|
||||||
|
builder.append(replace);
|
||||||
|
last_pos = pos + search.length();
|
||||||
}
|
}
|
||||||
|
builder.append(s, last_pos, std::string::npos);
|
||||||
|
s = std::move(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string gguf_kv_to_str(const struct gguf_context * ctx_gguf, int i) {
|
static std::string gguf_kv_to_str(const struct gguf_context * ctx_gguf, int i) {
|
||||||
|
@ -31,11 +31,17 @@ void llama_log_callback_default(ggml_log_level level, const char * text, void *
|
|||||||
|
|
||||||
static void replace_all(std::string & s, const std::string & search, const std::string & replace) {
|
static void replace_all(std::string & s, const std::string & search, const std::string & replace) {
|
||||||
if (search.empty()) {
|
if (search.empty()) {
|
||||||
return; // Avoid infinite loop if 'search' is an empty string
|
return;
|
||||||
}
|
}
|
||||||
|
std::string builder;
|
||||||
|
builder.reserve(s.length());
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
while ((pos = s.find(search, pos)) != std::string::npos) {
|
size_t last_pos = 0;
|
||||||
s.replace(pos, search.length(), replace);
|
while ((pos = s.find(search, last_pos)) != std::string::npos) {
|
||||||
pos += replace.length();
|
builder.append(s, last_pos, pos - last_pos);
|
||||||
|
builder.append(replace);
|
||||||
|
last_pos = pos + search.length();
|
||||||
}
|
}
|
||||||
|
builder.append(s, last_pos, std::string::npos);
|
||||||
|
s = std::move(builder);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user