-
Notifications
You must be signed in to change notification settings - Fork 5.9k
ENH: unify PADDLE_ENFORCE for cublas, cudnn, curand #2883
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
Conversation
| GPUPlaceGuard guard(gpu_place_); | ||
| paddle::platform::throw_on_error(cudaStreamCreate(&stream_), | ||
| "cudaStreamCreate failed"); | ||
| PADDLE_ENFORCE(cudaStreamCreate(&stream_), "cudaStreamCreate failed"); |
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.
PADDLE_ENFORCE means the condition must be true. But CUXXXX_STATUS_SUCCESS is zero, and false. So it seems that these lines should be
PADDLE_ENFORCE(cudaStreamCreate(&stream_) == CUDA_SUCCESS);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.
In my opinion, PADDLE_ENFORCE(condition, ...) means condition must execute correctly. No matter the return of condition is 0 or 1, the internal of PADDLE_ENFORCE can figure out how to deal with it.
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.
Agree with @reyoung. I check on how glog does. What CHECK does is to check the condition is true.
And we can implement CUDNN_ENFORCE/CUBLAS_ENFORCE based on PADDLE_ENFORCE for writing related codes more conveniently
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.
Given that
PADDLE_ENFORCE(cudaStreamCreate(&stream_))is shorter than
PADDLE_ENFORCE(cudaStreamCreate(&stream_) == CUDA_SUCCESS);and it is compatible with the use of the word "enforce" in English, I support that we adopt @gangliao 's proposal -- to make PADDLE_ENFORCE handle the condition.
I agree the English word CHECK should be followed by a boolean value and expects to be true. My point is that ENFORCE should be followed by an action, which is hopefully successful.
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.
Yeah, @wangkuiyi
PADDLE_ENFORCE(cudaStreamCreate(&stream_) == CUDA_SUCCESS);
will also impede us to print apposite error info for cuda, cudnn, cublas, curand.
paddle/platform/enforce.h
Outdated
|
|
||
| template <typename... Args> | ||
| inline void throw_on_error(cudaError_t e, const Args&... args) { | ||
| if (e) { |
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.
It seems that this snippet
if (e) {
std::stringstream ss;
ss << ::paddle::string::Sprintf(args...);
ss << ::paddle::string::Sprintf(" at [%s:%s];", __FILE__, __LINE__);
throw thrust::system_error(e, thrust::cuda_category(), ss.str());
}can be rewritten as
if (e) {
throw thrust::system_error(e, thrust::cuda_category(),
string::Sprintf(args...) + string::Sprintf(" at "...));
}I assume that we can write string::Sprintf other than ::paddle::string::Sprintf.
paddle/platform/enforce.h
Outdated
| std::string all_msg_; | ||
| }; | ||
|
|
||
| // From https://stackoverflow.com/questions/30130930/ |
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.
How about rephrase this comment:
// Because most enforce conditions would evaluate to true, we can use
// __builtin_expect to instruct the C++ compiler to generate code that always forces
// branch prediction of true. This generates faster binary code. For more details,
// please check https://stackoverflow.com/a/43870188/724872. __builtin_expect
// is since C++11.
paddle/platform/enforce.h
Outdated
| template <typename... Args> | ||
| inline void throw_on_error(int stat, const Args&... args) { | ||
| if (UNLIKELY(!(stat))) { | ||
| PADDLE_THROW(args...); |
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.
It seems that we don't really need PADDLE_THROW or EnforceNotMet; instead, we can call
throw std::runtime_error(...);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.
I totally agree with you, I will remove EnforceNotMet and PADDLE_THROW
paddle/platform/enforce.h
Outdated
| #define PADDLE_THROW(...) \ | ||
| do { \ | ||
| throw ::paddle::platform::EnforceNotMet( \ | ||
| ::paddle::string::Sprintf(__VA_ARGS__), __FILE__, __LINE__); \ |
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.
I noticed that paddle::string doesn't call paddle::platform now, so it is safe to make paddle::platform call paddle::string. I think this is the right calling direction. Thanks!
| #ifndef PADDLE_ONLY_CPU | ||
|
|
||
| template <typename... Args> | ||
| inline void throw_on_error(cudaError_t e, const Args&... args) { |
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.
How about we don't make these throw_on_error variants inline functions, but just normal functions, so we could move their implementations into a .cc file and make this header files concise and clean? It seems that this wouldn't degrade the performance of PADDLE_ENFORECE.
It looks to me that it's reasonable to keep this header file short; currently, the #ifndef PADDLE_ONLY_CPU check spans over too many lines.
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.
That's a good idea, but enforce.h is always frequently used in almost all source files.
If we separate it to *.h,*.cc, then almost all files have to compile with libenforce.a as follows:
cc_library(each_file SRCS each_file.cc DEPS enforce)That's quite annoying.
| #endif // PADDLE_ONLY_CPU | ||
|
|
||
| template <typename... Args> | ||
| inline void throw_on_error(int stat, const Args&... args) { |
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.
In addition to a int stat variant, should we also have a bool variant? I noticed applications like
PADDLE_ENFORCE(paddle::platform::is_cpu_place(self.place()),
"Only CPU tensor can cast to numpy array");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.
I will double check this, because we already use bool condition in our tensor implementation, but it didn't throw a error.
|
The pr modifies many files, does it modify automatically or by hand? |
|
@QiJune Using IDE or Modern editor like VS CODE can easily achieve this. |
No description provided.