ggml : process data in smaller chunks in CUDA ggml_top_k() implementation to reduce temporary buffers memory usage - #24776
Conversation
…tion to reduce temporary buffers memory usage
| for (int64_t i = 0; i < nrows; i+= nrows_per_chunk) { | ||
| int64_t chunk_nrows = std::min(nrows_per_chunk, nrows - i); | ||
|
|
||
| ggml_cuda_pool_alloc<int> temp_dst_alloc(pool, ncols * chunk_nrows); |
There was a problem hiding this comment.
I'm not sure how the cuda pool works exactly - just wondering if we actually need to have this allocation inside the loop and not one time before it?
There was a problem hiding this comment.
I'm not sure how the cuda pool works exactly - just wondering if we actually need to have this allocation inside the loop and not one time before it?
@ggerganov Good point, will try it out.
Co-authored-by: Georgi Gerganov <ggerganov@gmail.com>
|
@ORippler Do you envision any problems with organizing top-k processing the way I did it in this PR (added loop processing smaller input chunks, temporary buffer allocated outside the loop)? |
No general problems with doing it this way. Some remarks:
|
@ORippler OK, will put the number of chunk rows calculation into a common function and apply this to argsort as well. |
…gml_top_k() implementation to reduce temporary buffers memory usage
| const int chunk_nrows = chunk_bytes > nb01 ? chunk_bytes / nb01 : 1; | ||
|
|
||
| // limit the resulting amount to total nrows | ||
| return nrows < chunk_nrows ? nrows : chunk_nrows; |
There was a problem hiding this comment.
Preferably use std::max and std::min here.
There was a problem hiding this comment.
Preferably use
std::maxandstd::minhere.
@JohannesGaessler Done, there were two more ternary operators so I included them as well.
…ement Co-authored-by: Johannes Gäßler <johannesg@5d6.de>
ORippler
left a comment
There was a problem hiding this comment.
OK, will put the number of chunk rows calculation into a common function and apply this to argsort as well.
Thanks for moving this to a shared helper! LGTM. Note there are more ternary expressions beyond the one in argsort_f32_i32_cuda_cub_chunk_nrows that could also be changed
…rgsort() to reduce temporary buffers memory usage (ggml-org#24776) * ggml : process data in smaller chunks in CUDA ggml_top_k() implementation to reduce temporary buffers memory usage * ggml : allocate tmp_dst only only once before the loop * chore : whitespaces Co-authored-by: Georgi Gerganov <ggerganov@gmail.com> * ggml : use chunked processing in both CUDA CUB top-k and argsort implementations * chore : separate argsort_f32_i32_cuda_bitonic() call from return statement Co-authored-by: Johannes Gäßler <johannesg@5d6.de> * chore : replace ternary operators with min/max --------- Co-authored-by: Stanisław Szymczyk <sszymczy@gmail.com> Co-authored-by: Georgi Gerganov <ggerganov@gmail.com> Co-authored-by: Johannes Gäßler <johannesg@5d6.de>
…rgsort() to reduce temporary buffers memory usage (ggml-org#24776) * ggml : process data in smaller chunks in CUDA ggml_top_k() implementation to reduce temporary buffers memory usage * ggml : allocate tmp_dst only only once before the loop * chore : whitespaces Co-authored-by: Georgi Gerganov <ggerganov@gmail.com> * ggml : use chunked processing in both CUDA CUB top-k and argsort implementations * chore : separate argsort_f32_i32_cuda_bitonic() call from return statement Co-authored-by: Johannes Gäßler <johannesg@5d6.de> * chore : replace ternary operators with min/max --------- Co-authored-by: Stanisław Szymczyk <sszymczy@gmail.com> Co-authored-by: Georgi Gerganov <ggerganov@gmail.com> Co-authored-by: Johannes Gäßler <johannesg@5d6.de>
Overview
This PR reduces temporary buffers memory usage in CUDA backend
ggml_top_k()CUB implementation by processing input data in smaller chunks. Without this PR temporary buffers memory usage is 3 * input buffer size, allocated here:llama.cpp/ggml/src/ggml-cuda/top-k.cu
Line 79 in d5376cf
and here:
llama.cpp/ggml/src/ggml-cuda/argsort.cu
Lines 38 to 39 in d5376cf
With this PR memory usage for temporary buffers is only 3*min(input buffer size, 64MiB).
It also partially mitigates the problem of integer overflow in
ncols * nrowsproduct by lowering the amount of rows processed at once.Fixes #24718
Additional information
For example when running this test (not present originally, I added it):
without this PR memory usage in
nvidia-smigoes up to 12968MiB, while with this PR it goes up only to 3048MiB.Let's also compare the performance. Without this PR:
with this PR:
I ran
test-backend-opsTOP-K tests and they all passed. Test failing in #24718 also passed:Requirements