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

Follow changes from #3959 #362

Merged
merged 2 commits into from
Aug 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ py::dict getRecords(const std::string & id) {
using sofa::helper::system::thread::CTime;

static auto timer_freq = CTime::getTicksPerSec();
auto getTime = [](ctime_t t) {
return 1000.0 * t / timer_freq;
auto getTime = [](ctime_t t)
{
return 1000 * t / timer_freq;
};

const auto records = AdvancedTimer::getRecords(id);
Expand All @@ -49,97 +50,118 @@ py::dict getRecords(const std::string & id) {
tokens.push(token);
ctime_t t0;

for (const auto & r : records) {
switch (r.type) {
case Record::RNONE:
break;
case Record::RBEGIN: // Timer begins
token = tokens.top();
if (token.contains(r.label.c_str())) {
if (py::list::check_(token[r.label.c_str()])) {
token_temp = py::dict();
py::list(token[r.label.c_str()]).append(token_temp);
token = token_temp;
} else if (py::dict::check_(token[r.label.c_str()])) {
token_temp = token[r.label.c_str()];
token[r.label.c_str()] = py::list();
py::list(token[r.label.c_str()]).append(token_temp);
token_temp = py::dict();
py::list(token[r.label.c_str()]).append(token_temp);
token = token_temp;
} else {
msg_error("Timer::getRecords") << "Got an unexpected token of type '" << std::string(py::str(token.get_type())) << "'.";
break;
}
} else {
token[r.label.c_str()] = py::dict();
token = token[r.label.c_str()];
for (const auto& r : records)
{
switch (r.type)
{
case Record::RNONE:
break;
case Record::RBEGIN: // Timer begins
token = tokens.top();
if (token.contains(r.label.c_str()))
{
if (py::list::check_(token[r.label.c_str()]))
{
token_temp = py::dict();
py::list(token[r.label.c_str()]).append(token_temp);
token = token_temp;
}
t0 = r.time;
token["start_time"] = getTime(r.time - t0);
tokens.push(token);
break;
case Record::REND: // Timer ends
token = tokens.top();
token["end_time"] = getTime(r.time - t0);
token["total_time"] = getTime(r.time - t0) - py::cast<float>(token["start_time"]);
tokens.pop();
break;
case Record::RSTEP_BEGIN: // Step begins
token = tokens.top();
if (token.contains(r.label.c_str())) {
if (py::list::check_(token[r.label.c_str()])) {
token_temp = py::dict();
py::list(token[r.label.c_str()]).append(token_temp);
token = token_temp;
} else if (py::dict::check_(token[r.label.c_str()])) {
token_temp = token[r.label.c_str()];
token[r.label.c_str()] = py::list();
py::list(token[r.label.c_str()]).append(token_temp);
token_temp = py::dict();
py::list(token[r.label.c_str()]).append(token_temp);
token = token_temp;
} else {
msg_error("Timer::getRecords") << "Got an unexpected token of type '" << std::string(py::str(token.get_type())) << "'.";
break;
}
} else {
token[r.label.c_str()] = py::dict();
token = token[r.label.c_str()];
else if (py::dict::check_(token[r.label.c_str()]))
{
token_temp = token[r.label.c_str()];
token[r.label.c_str()] = py::list();
py::list(token[r.label.c_str()]).append(token_temp);
token_temp = py::dict();
py::list(token[r.label.c_str()]).append(token_temp);
token = token_temp;
}
token["start_time"] = getTime(r.time - t0);
tokens.push(token);
break;
case Record::RSTEP_END: // Step ends
token = tokens.top();
token["end_time"] = getTime(r.time - t0);
token["total_time"] = getTime(r.time - t0) - py::cast<float>(token["start_time"]);
tokens.pop();
break;
case Record::RVAL_SET: // Sets a value
token = tokens.top();
token[r.label.c_str()] = r.val;
break;
case Record::RVAL_ADD: // Sets a value
token = tokens.top();
token[r.label.c_str()] = r.val;
break;
default:
token = tokens.top();
token[r.label.c_str()] = py::list();
else
{
msg_error("Timer::getRecords") << "Got an unexpected token of type '" << std::string(py::str(token.get_type())) << "'.";
break;
}
}
else
{
token[r.label.c_str()] = py::dict();
token = token[r.label.c_str()];
token["start_time"] = r.time;
break;
}
t0 = r.time;
token["start_time"] = getTime(r.time - t0);
tokens.push(token);
break;
case Record::REND: // Timer ends
token = tokens.top();
token["end_time"] = getTime(r.time - t0);
token["total_time"] = getTime(r.time - t0) - py::cast<float>(token["start_time"]);
tokens.pop();
break;
case Record::RSTEP_BEGIN: // Step begins
token = tokens.top();
if (token.contains(r.label.c_str()))
{
if (py::list::check_(token[r.label.c_str()]))
{
token_temp = py::dict();
py::list(token[r.label.c_str()]).append(token_temp);
token = token_temp;
}
else if (py::dict::check_(token[r.label.c_str()]))
{
token_temp = token[r.label.c_str()];
token[r.label.c_str()] = py::list();
py::list(token[r.label.c_str()]).append(token_temp);
token_temp = py::dict();
py::list(token[r.label.c_str()]).append(token_temp);
token = token_temp;
}
else
{
msg_error("Timer::getRecords") << "Got an unexpected token of type '" << std::string(py::str(token.get_type())) << "'.";
break;
}
}
else
{
token[r.label.c_str()] = py::dict();
token = token[r.label.c_str()];
}
token["start_time"] = getTime(r.time - t0);
tokens.push(token);
break;
case Record::RSTEP_END: // Step ends
token = tokens.top();
token["end_time"] = getTime(r.time - t0);
token["total_time"] = getTime(r.time - t0) - py::cast<float>(token["start_time"]);
tokens.pop();
break;
case Record::RVAL_SET: // Sets a value
token = tokens.top();
token[r.label.c_str()] = r.val;
break;
case Record::RVAL_ADD: // Sets a value
token = tokens.top();
token[r.label.c_str()] = r.val;
break;
default:
token = tokens.top();
token[r.label.c_str()] = py::list();
token = token[r.label.c_str()];
token["start_time"] = r.time;
break;
}
}

// There should be two remaining records: Top level "record" + "timer starts". The "timer starts" record remains in
// the stack since we normally get the records before the timer ends (ending the timer in Sofa destroys the
// records...)
if (tokens.size() == 2) {
if (tokens.size() == 2)
{
token = tokens.top();
tokens.pop();
} else if (tokens.size() == 1) {
}
else if (tokens.size() == 1)
{
// This should not happen unless we successfully got the timer records AFTER the timer has ends, which would mean
// that Sofa's advanced timer has improved, let not warn the user for that.
token = tokens.top();
Expand All @@ -150,7 +172,9 @@ py::dict getRecords(const std::string & id) {

// The stack should be empty by now
if (!tokens.empty())
{
msg_error("Timer::getRecords") << "Records stack leaked.";
}

return token;
}
Expand Down
10 changes: 5 additions & 5 deletions examples/advanced_timer.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ def onAnimateEndEvent(self, event):
else:
records = Timer.getRecords("cg_timer")

step_time = records['AnimateVisitor']['Mechanical (meca)']['total_time']
step_time = records['solve']['Mechanical (meca)']['total_time']
print(f"Step took {step_time:.2f} ms")

nb_iterations = records['AnimateVisitor']['Mechanical (meca)']['StaticSolver::Solve']['nb_iterations']
nb_iterations = records['solve']['Mechanical (meca)']['StaticSolver::Solve']['nb_iterations']
for i in range(int(nb_iterations)):
total_time = records['AnimateVisitor']['Mechanical (meca)']['StaticSolver::Solve']['NewtonStep'][i]['total_time']
CG_iterations = records['AnimateVisitor']['Mechanical (meca)']['StaticSolver::Solve']['NewtonStep'][i]['MBKSolve']['CG iterations']
total_time = records['solve']['Mechanical (meca)']['StaticSolver::Solve']['NewtonStep'][i]['total_time']
CG_iterations = records['solve']['Mechanical (meca)']['StaticSolver::Solve']['NewtonStep'][i]['MBKSolve']['CG iterations']
print(f" Newton iteration #{i} took {total_time:.2f} ms using {int(CG_iterations)} CG iterations")

if not self.use_sofa_profiler_timer:
Expand Down Expand Up @@ -66,7 +66,7 @@ def createScene(root):
root.addObject( TimerController() )

# Create a grid topology of 10x10x60 centered on (0,0,0)
root.addObject('RegularGridTopology', name='grid', min=[-5, -5, -30], max=[5, 5, 30], n=[11, 11, 61])
root.addObject('RegularGridTopology', name='grid', min=[-5, -5, -30], max=[5, 5, 30], n=[6, 6, 16])

# Create our mechanical node
root.addChild("meca")
Expand Down
Loading