Skip to content

Commit b8f5e8c

Browse files
committed
rpc : put cache under $HOME/.cache/llama.cpp
1 parent c04dfdf commit b8f5e8c

File tree

2 files changed

+123
-16
lines changed

2 files changed

+123
-16
lines changed

examples/rpc/rpc-server.cpp

Lines changed: 122 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,12 @@
1818

1919
#include "ggml-rpc.h"
2020
#ifdef _WIN32
21+
# define DIRECTORY_SEPARATOR '\\'
2122
# include <windows.h>
2223
#else
24+
# define DIRECTORY_SEPARATOR '/'
2325
# include <unistd.h>
26+
# include <sys/stat.h>
2427
#endif
2528
#include <string>
2629
#include <stdio.h>
@@ -29,11 +32,114 @@
2932

3033
namespace fs = std::filesystem;
3134

35+
// NOTE: this is copied from common.cpp to avoid linking with libllama
36+
// returns true if successful, false otherwise
37+
static bool fs_create_directory_with_parents(const std::string & path) {
38+
#ifdef _WIN32
39+
std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
40+
std::wstring wpath = converter.from_bytes(path);
41+
42+
// if the path already exists, check whether it's a directory
43+
const DWORD attributes = GetFileAttributesW(wpath.c_str());
44+
if ((attributes != INVALID_FILE_ATTRIBUTES) && (attributes & FILE_ATTRIBUTE_DIRECTORY)) {
45+
return true;
46+
}
47+
48+
size_t pos_slash = 0;
49+
50+
// process path from front to back, procedurally creating directories
51+
while ((pos_slash = path.find('\\', pos_slash)) != std::string::npos) {
52+
const std::wstring subpath = wpath.substr(0, pos_slash);
53+
const wchar_t * test = subpath.c_str();
54+
55+
const bool success = CreateDirectoryW(test, NULL);
56+
if (!success) {
57+
const DWORD error = GetLastError();
58+
59+
// if the path already exists, ensure that it's a directory
60+
if (error == ERROR_ALREADY_EXISTS) {
61+
const DWORD attributes = GetFileAttributesW(subpath.c_str());
62+
if (attributes == INVALID_FILE_ATTRIBUTES || !(attributes & FILE_ATTRIBUTE_DIRECTORY)) {
63+
return false;
64+
}
65+
} else {
66+
return false;
67+
}
68+
}
69+
70+
pos_slash += 1;
71+
}
72+
73+
return true;
74+
#else
75+
// if the path already exists, check whether it's a directory
76+
struct stat info;
77+
if (stat(path.c_str(), &info) == 0) {
78+
return S_ISDIR(info.st_mode);
79+
}
80+
81+
size_t pos_slash = 1; // skip leading slashes for directory creation
82+
83+
// process path from front to back, procedurally creating directories
84+
while ((pos_slash = path.find('/', pos_slash)) != std::string::npos) {
85+
const std::string subpath = path.substr(0, pos_slash);
86+
struct stat info;
87+
88+
// if the path already exists, ensure that it's a directory
89+
if (stat(subpath.c_str(), &info) == 0) {
90+
if (!S_ISDIR(info.st_mode)) {
91+
return false;
92+
}
93+
} else {
94+
// create parent directories
95+
const int ret = mkdir(subpath.c_str(), 0755);
96+
if (ret != 0) {
97+
return false;
98+
}
99+
}
100+
101+
pos_slash += 1;
102+
}
103+
104+
return true;
105+
#endif // _WIN32
106+
}
107+
108+
// NOTE: this is copied from common.cpp to avoid linking with libllama
109+
static std::string fs_get_cache_directory() {
110+
std::string cache_directory = "";
111+
auto ensure_trailing_slash = [](std::string p) {
112+
// Make sure to add trailing slash
113+
if (p.back() != DIRECTORY_SEPARATOR) {
114+
p += DIRECTORY_SEPARATOR;
115+
}
116+
return p;
117+
};
118+
if (getenv("LLAMA_CACHE")) {
119+
cache_directory = std::getenv("LLAMA_CACHE");
120+
} else {
121+
#ifdef __linux__
122+
if (std::getenv("XDG_CACHE_HOME")) {
123+
cache_directory = std::getenv("XDG_CACHE_HOME");
124+
} else {
125+
cache_directory = std::getenv("HOME") + std::string("/.cache/");
126+
}
127+
#elif defined(__APPLE__)
128+
cache_directory = std::getenv("HOME") + std::string("/Library/Caches/");
129+
#elif defined(_WIN32)
130+
cache_directory = std::getenv("LOCALAPPDATA");
131+
#endif // __linux__
132+
cache_directory = ensure_trailing_slash(cache_directory);
133+
cache_directory += "llama.cpp";
134+
}
135+
return ensure_trailing_slash(cache_directory);
136+
}
137+
32138
struct rpc_server_params {
33-
std::string host = "127.0.0.1";
34-
int port = 50052;
35-
size_t backend_mem = 0;
36-
std::string cache_dir = "";
139+
std::string host = "127.0.0.1";
140+
int port = 50052;
141+
size_t backend_mem = 0;
142+
bool use_cache = false;
37143
};
38144

39145
static void print_usage(int /*argc*/, char ** argv, rpc_server_params params) {
@@ -42,8 +148,8 @@ static void print_usage(int /*argc*/, char ** argv, rpc_server_params params) {
42148
fprintf(stderr, " -h, --help show this help message and exit\n");
43149
fprintf(stderr, " -H HOST, --host HOST host to bind to (default: %s)\n", params.host.c_str());
44150
fprintf(stderr, " -p PORT, --port PORT port to bind to (default: %d)\n", params.port);
45-
fprintf(stderr, " -d DIR, --cache-dir DIR local cache dir\n");
46151
fprintf(stderr, " -m MEM, --mem MEM backend memory size (in MB)\n");
152+
fprintf(stderr, " -c, --cache enable local file cache\n");
47153
fprintf(stderr, "\n");
48154
}
49155

@@ -64,16 +170,8 @@ static bool rpc_server_params_parse(int argc, char ** argv, rpc_server_params &
64170
if (params.port <= 0 || params.port > 65535) {
65171
return false;
66172
}
67-
} else if (arg == "-d" || arg == "--cache-dir") {
68-
if (++i >= argc) {
69-
return false;
70-
}
71-
fs::path cache_dir(argv[i]);
72-
if (!fs::is_directory(cache_dir)) {
73-
fprintf(stderr, "error: cache dir does not exist: %s\n", cache_dir.c_str());
74-
return false;
75-
}
76-
params.cache_dir = argv[i];
173+
} else if (arg == "-c" || arg == "--cache") {
174+
params.use_cache = true;
77175
} else if (arg == "-m" || arg == "--mem") {
78176
if (++i >= argc) {
79177
return false;
@@ -180,7 +278,15 @@ int main(int argc, char * argv[]) {
180278
} else {
181279
get_backend_memory(&free_mem, &total_mem);
182280
}
183-
const char * cache_dir = params.cache_dir.empty() ? nullptr : params.cache_dir.c_str();
281+
const char * cache_dir = nullptr;
282+
std::string cache_dir_str = fs_get_cache_directory() + "rpc/";
283+
if (params.use_cache) {
284+
if (!fs_create_directory_with_parents(cache_dir_str)) {
285+
fprintf(stderr, "Failed to create cache directory: %s\n", cache_dir_str.c_str());
286+
return 1;
287+
}
288+
cache_dir = cache_dir_str.c_str();
289+
}
184290
printf("Starting RPC server\n");
185291
printf(" endpoint : %s\n", endpoint.c_str());
186292
printf(" local cache : %s\n", cache_dir ? cache_dir : "n/a");

ggml/src/ggml-rpc/ggml-rpc.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,6 +1013,7 @@ bool rpc_server::set_tensor(const std::vector<uint8_t> & input) {
10131013
fs::path cache_file = fs::path(cache_dir) / hash_str;
10141014
std::ofstream ofs(cache_file, std::ios::binary);
10151015
ofs.write((const char *)data, size);
1016+
printf("[%s] saved to '%s'\n", __func__, cache_file.c_str());
10161017
}
10171018
ggml_backend_tensor_set(tensor, data, offset, size);
10181019
ggml_free(ctx);

0 commit comments

Comments
 (0)