Skip to content
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

[Logging] Add DMLC_NO_INLINE to LogMessageFatal #615

Merged

Conversation

junrushao
Copy link
Member

@junrushao junrushao commented May 21, 2020

A follow-up PR of #613

Below are the benchmarks we did. We use g++ -fstack-usage to dump the stack usage information for the target function.

Settings:

  • Compiler: g++ 5.4
  • OS: Ubuntu 18.04
  • Stack size: ulimit -s 8192
  • Target function: virtual tvm::relay::Expr tvm::relay::CommonSubexprEliminator::VisitExpr_(const tvm::relay::CallNode*), which originally crashed this PR on a very deep network

Results:

This patch Patch #613 No patch dmlc-core
CHECK 544 560 4656
throw dmlc::Error 736 1264
throw std::runtime_error 480 1008
No checks (no-op) 480 1008

See also: apache/tvm#5585

CC: @tqchen @trivialfis

@junrushao junrushao force-pushed the feature/2020-05-20/stack-usage-strikes-back branch from 37c77e6 to 6d84163 Compare May 21, 2020 03:01
return dmlc::Error(log_stream.str());
}
DMLC_NO_INLINE static Entry *ThreadLocal() {
static thread_local Entry *result = new Entry();
Copy link
Member Author

@junrushao junrushao May 21, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The introduction of TLS helps to reduce the size of class dmlc::LogMessageFatal to zero, which enables some opportunities in compiler optimization

@hcho3
Copy link
Contributor

hcho3 commented May 21, 2020

@trivialfis Can you review?

Copy link
Contributor

@hcho3 hcho3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

std::ostringstream &stream() { return log_stream_; }
~LogMessageFatal() DMLC_THROW_EXCEPTION {
std::ostringstream &stream() { return Entry::ThreadLocal()->log_stream; }
DMLC_NO_INLINE ~LogMessageFatal() DMLC_THROW_EXCEPTION {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The no-inline trick here instructs the compiler not to merge the complicated logic of throwing in the destructor into the caller. This usually wouldn't hurt performance because it is quite a slow path

#endif
throw Error(log_stream_.str());
throw Entry::ThreadLocal()->Finalize();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We moved all the logic except throw itself to another class, to make sure the unsafe region is minimized

@junrushao
Copy link
Member Author

Logging.basics is failing and I am trying to understand the reason

@hcho3
Copy link
Contributor

hcho3 commented May 21, 2020

@junrushao1994 Somehow this line is not being honored:

#define DMLC_LOG_FATAL_THROW 0

@tqchen
Copy link
Member

tqchen commented May 21, 2020

Merging this for now. We should also migrate the windows test to the action later.

@tqchen tqchen merged commit 6c401e2 into dmlc:master May 21, 2020
@tqchen
Copy link
Member

tqchen commented May 21, 2020

We can refer to the windows pipeline of TVM

@tqchen
Copy link
Member

tqchen commented May 21, 2020

@junrushao
Copy link
Member Author

Hmmm i am not so sure why it happens. Is there any symbol overriding that happens in dmlc_unit_tests? Or is there any amalgamation logic which makes one include ineffective?

@tqchen
Copy link
Member

tqchen commented May 21, 2020

I am not too sure either, we should look into the cmakefile to see what was happening. One potential reason could due to the cmake cache if there is a separate libdmlc built with a different flag

@tqchen
Copy link
Member

tqchen commented May 21, 2020

Here is a guess, it could be possible that we links every test into a single app. then the config in https://github.com/dmlc/dmlc-core/blob/master/test/unittest/unittest_logging.cc conflicts with the fatal throw one. Perhaps we should just unify the two tests if that is the case

@tqchen
Copy link
Member

tqchen commented May 21, 2020

@junrushao1994 can you open a followup PR to do that?

@junrushao
Copy link
Member Author

@tqchen to unify those two tests by changing both of their macro to 1?

@tqchen
Copy link
Member

tqchen commented May 21, 2020

Yes, you might also need to update the ASSERT_DEATH a bit by changing that to throw

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants