-
Notifications
You must be signed in to change notification settings - Fork 3.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix single row prediction performance in a multi-threaded environment #6024
Fix single row prediction performance in a multi-threaded environment #6024
Conversation
Fixes microsoft#6021 - Store all resources that are reused across single-row predictions in the dedicated `SingleRowPredictor` (aka `FastConfig`) - Use that instead of resources in the `Booster` when doing single row predictions to avoid having to lock the `Booster` exclusively. - A FastConfig being alive now takes a shared lock on the booster (it was likely very incorrect to mutate the booster while this object was already built anyway)
Workflows run would help :) (not sure what is currently using this and should be tested) |
@microsoft-github-policy-service agree |
846dc01
to
f0e4227
Compare
You don't need to force-push here. All commits will be squashed on merge. |
…SingleRowPredictor
Thanks! :) That was just me organizing my work though (I wanted this commit specifically to be a single one and working in case it would end up being reverted) |
f0e4227
to
f41755b
Compare
@shiyu1994 or @guolinke could you please help with a review on this one? And @AlbertoEAF if you have time? |
@Ten0 thanks for contributing! Since we're adding capability for it, can you add a test to our C++ test suite showing multiple predictors using the fast API and sharing the booster? |
So I've finished my benchmarks and it turns out:
|
Thanks a lot @Ten0 for this commit. I am a new user of lightGBM(need to mention this so that you don't confuse me with a veteran).
Is this understanding correct? |
Of |
Sorry, but I didn't mean that. I really meant
Here is the pseudo-code, would need to fill #include <iostream>
#include <thread>
#include <vector>
#include "LightGBM/c_api.h"
// # of features
const int kFeatures = 13;
// # of threads which call predict
const int nworkers = 10;
// Shared booster
BoosterHandle booster_handle;
// Every thread exectues this function
void predict(ssize_t beg, ssize_t end) {
// Each thread has its own FastConfigHandle
FastConfigHandle config;
int rc = LGBM_BoosterPredictForMatSingleRowFastInit(
booster_handle, C_API_PREDICT_NORMAL, 0, 0, C_API_DTYPE_FLOAT64,
kFeatures, "", &config);
if (rc != 0) {
abort();
}
for (ssize_t i = beg; i < end; i++) {
int64_t len = 0;
rc = LGBM_BoosterPredictForMatSingleRowFast(config, ...);
}
}
int main(int argc, char* argv[]) {
int num_iterations;
int rc = LGBM_BoosterCreateFromModelfile(argv[1], &num_iterations,
&booster_handle);
if (rc != 0) {
std::cout << "LGBM_BoosterCreateFromModelfile() returned " << rc << '\n';
return 1;
}
std::vector<std::thread> workers(nworkers);
for (ssize_t i = 0; i < nworkers; i++) {
if (i != nworkers - 1) {
workers[i] = std::thread(predict, ...);
}
}
for (std::thread& t : workers) {
t.join();
}
return 0;
}
If each thread creates its own Let me know if my understanding of API usage is correct or not. I want to use your fork(because I need scalable predict/inference performance) |
Your understanding is correct, it seems to be just a matter of definitions that caused our misunderstanding. (
Happy to help :) |
f54a6e2
to
6db33b3
Compare
TLDR; All comments resolved.
That took a while to implement because a similar test didn't already exist (the C api was only tested through the python wrapper and the other implementations binding to it) but it's finally done! (1fcbc3f) I've also added a workaround for #6142. The state of this issue is that, with the workaround, users would not hit issues any more with this API than they would with the current existing APIs around both single row and matrix prediction. AFAICT this is ready for merge. Side note: we've been using this in production for a few months without any issue (with the workaround implemented in the wrapper) |
2022132
to
b3848a5
Compare
b3848a5
to
bf5fc5f
Compare
@guolinke Static analysis complains that the TODO tag (#6024 (comment)) is not assigned. Who should I assign it to? |
We prefer not using
Could you please put the content of that comment into a new issue at https://github.com/microsoft/LightGBM/issues with as much detail as necessary for someone else to pick it up (and linking to this PR)? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you!
Sorry, I'd missed that @guolinke approved this back in January! I've just updated it to latest |
Thanks very much! |
Fixes #6021
SingleRowPredictor
(akaFastConfig
)Booster
when doing Fast™ single row predictions to avoid having to lock theBooster
exclusively.