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

Replace readItem in ProcessNumber to speed-up SolarShadingTest_ImportedShading #8819

Merged
merged 4 commits into from
Jun 21, 2021

Conversation

mitchute
Copy link
Collaborator

Pull request overview

Runtimes for SolarShadingTest_ImportedShading
Before
Run 1: 170.00 s
Run 2: 173.31 s
Run 3: 156.62 s

After
Run 1: 15.77 s
Run 2: 15.25 s
Run 3: 10.68 s
Run 4: 11.55 s
Run 5: 12.32 s

Pull Request Author

Add to this list or remove from it as applicable. This is a simple templated set of guidelines.

  • Title of PR should be user-synopsis style (clearly understandable in a standalone changelog context)
  • Label the PR with at least one of: Defect, Refactoring, NewFeature, Performance, and/or DoNoPublish
  • Pull requests that impact EnergyPlus code must also include unit tests to cover enhancement or defect repair
  • Author should provide a "walkthrough" of relevant code changes using a GitHub code review comment process
  • If any diffs are expected, author must demonstrate they are justified using plots and descriptions
  • If changes fix a defect, the fix should be demonstrated in plots and descriptions
  • If any defect files are updated to a more recent version, upload new versions here or on DevSupport
  • If IDD requires transition, transition source, rules, ExpandObjects, and IDFs must be updated, and add IDDChange label
  • If structural output changes, add to output rules file and add OutputChange label
  • If adding/removing any LaTeX docs or figures, update that document's CMakeLists file dependencies

Reviewer

This will not be exhaustively relevant to every PR.

  • Perform a Code Review on GitHub
  • If branch is behind develop, merge develop and build locally to check for side effects of the merge
  • If defect, verify by running develop branch and reproducing defect, then running PR and reproducing fix
  • If feature, test running new feature, try creative ways to break it
  • CI status: all green or justified
  • Check that performance is not impacted (CI Linux results include performance check)
  • Run Unit Test(s) locally
  • Check any new function arguments for performance impacts
  • Verify IDF naming conventions and styles, memos and notes and defaults
  • If new idf included, locally check the err file and other outputs

@mitchute mitchute added Performance Includes code changes that are directed at improving the runtime performance of EnergyPlus Refactoring Includes code changes that don't change the functionality of the program, just perform refactoring labels Jun 13, 2021
@mitchute mitchute added this to the EnergyPlus 9.6 Release milestone Jun 13, 2021
@mitchute mitchute self-assigned this Jun 13, 2021
@mitchute mitchute requested review from jmythms and mjwitte June 18, 2021 14:57
@jmythms
Copy link
Contributor

jmythms commented Jun 18, 2021

The run time differences are amazing. I wish we knew what was causing so much improvement in Mac builds, or, what was causing Mac builds to slow down so much with the original code. The runtimes in Linux builds only had an improvement from 8s to 5s. I wonder if it is something to do with the compiler we use for Mac builds, since the code is the same.

@mitchute
Copy link
Collaborator Author

I'm not sure what the issue is. readItem is a templated function, so maybe that has something to do with it. Maybe in the future we can move away from readItem for parsing strings. What did you do in the ScheduleManager refactor?

@jmythms
Copy link
Contributor

jmythms commented Jun 18, 2021

The ScheduleManager refactor is focused on decreasing unnecessary file open, close operations where they can be avoided. I was using the original ProcessNumber function in it. The improvements from this PR will definitely add to the effects of the ScheduleManager refactor.

@jmythms
Copy link
Contributor

jmythms commented Jun 18, 2021

Since ProcessNumber is used in three places in ScheduleManager.cc, any case that uses those parts of the code should see improvements from this PR:

  1. Schedule:File:Shading
  2. Schedule:Compact
  3. Schedule:File

Copy link
Contributor

@mjwitte mjwitte left a comment

Choose a reason for hiding this comment

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

@mitchute Similar timing results on Windows (just one run each, so not super accurate):
SolarShadingTest_ExternalFraction went from 214s to 113s
SolarShadingTest_ImportedShading went from 118s to 10s

This looks good so far. It would be good to have a unit test that exercises the new catch blocks. I've tested one path with bad values in Schedule;Compact and in the csv (I think), but a unit test that covers all the flavors of numbers this could see including bad values would be useful.

@mitchute
Copy link
Collaborator Author

Thanks, @mjwitte. Yes, I was going to do that but it looks like I didn't get it done. I'll work one up.

ErrorFlag = false;
try {
rProcessNumber = std::stod(PString, nullptr);
ErrorFlag = false;
Copy link
Contributor

Choose a reason for hiding this comment

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

ErrorFlag = false is already set at line 128. Delete line 138. Also, remember the discussion long ago about setting a function argument bool &ErrorFlag to false within any function. It's OK to set it true, but don't set it to false which would erase any previous error. To that end I would delete line 128 as well. @mjwitte.

I am amazed at the impact this has on execution speed!

Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like there are several places in code where this function is called that relies on ErrorFlag being true or false for each specific call. So do not delete line 128,

@mitchute
Copy link
Collaborator Author

OK, the unit test has been added. I marked the std::invalid_argument exception to be skipped for coverage results. I can't make it fall in there with any of the following:

"3.14159+0" - returns 3.14159
"3.14159.0" - returns 3.14159
"3.14159+-0" - returns 3.14159
"3.14159-E-0" - returns 3.14159

Maybe we should also be checking for multiple "+", "-", ".", and "E" (or similar, "d", "D", or "e"). It looks like std::stod just reads up to the first place where it finds a valid number and returns that.

@mitchute
Copy link
Collaborator Author

Ah, I figured out the invalid_argument exception. "E3.14159" will fall in there. I'll fix that up.

Anything else?

Copy link
Contributor

@rraustad rraustad left a comment

Choose a reason for hiding this comment

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

This all looks good with a remarkable improvement in execution speed.

@rraustad
Copy link
Contributor

OK, the unit test has been added. I marked the std::invalid_argument exception to be skipped for coverage results. I can't make it fall in there with any of the following:

"3.14159+0" - returns 3.14159
"3.14159.0" - returns 3.14159
"3.14159+-0" - returns 3.14159
"3.14159-E-0" - returns 3.14159

Maybe we should also be checking for multiple "+", "-", ".", and "E" (or similar, "d", "D", or "e"). It looks like std::stod just reads up to the first place where it finds a valid number and returns that.

With this speed improvement, wouldn't it be smarter to catch that in the input processor?

@mitchute
Copy link
Collaborator Author

wouldn't it be smarter to catch that in the input processor?

I'm honestly not sure what the right path is currently. I think we'll find that this a part of all input processing, regardless of whether it happens in the InputProcessor. readItem is used explicitly all over the place to read in files, including the weather files. I was just looking at a file where my local profiler was saying that readItem was taking something like 20% of a 15-second simulation. We ought to take a look at seeing where we can eliminate it in other places.

@rraustad
Copy link
Contributor

rraustad commented Jun 18, 2021

Just a thought, could this be moved to the input processor for numeric inputs? That certainly does not have to happen in this branch since all looks good here.

        std::replace_if(
            std::begin(PString), std::end(PString), [](const char c) { return c == 'D' || c == 'd'; }, 'e');

@mitchute mitchute mentioned this pull request Jun 21, 2021
20 tasks
@jmythms
Copy link
Contributor

jmythms commented Jun 21, 2021

This looks good to me. Testing done:

  1. Checked with Fortran "numerics" like "2d3", the parsing worked well: Converted 2d3 to 2e3 and then to 2000.
  2. Strings like "asdf" changed the ErrorFlag to true.

Comment on lines +136 to +144
try {
rProcessNumber = std::stod(PString, nullptr);
} catch (std::invalid_argument &e) {
rProcessNumber = 0.0;
ErrorFlag = true;
} catch (std::out_of_range &e) {
rProcessNumber = 0.0;
ErrorFlag = true;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks great!

badString = "1E5000";
expectedVal = 0.0;
EXPECT_NEAR(UtilityRoutines::ProcessNumber(badString, expectedError), expectedVal, 1E-5);
EXPECT_TRUE(expectedError);
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this is comprehensive, and touched the cases I could think of.

@Myoldmopar
Copy link
Member

This is absolutely awesome! I'll look over the code changes now but this has been reviewed by multiple folks and looks like it has a great unit test in place. CI is really happy too.

Copy link
Member

@Myoldmopar Myoldmopar left a comment

Choose a reason for hiding this comment

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

OK this is ridiculous. What an impactful change!!!

@Myoldmopar
Copy link
Member

I'm going to build and run tests on this locally since I just merged in a couple PRs this morning. If it passes I'll merge. Thanks @mitchute for the work and @rraustad and @mjwitte for the reviews and testing!

@Myoldmopar
Copy link
Member

All clean with develop merged up. Thanks all.

@Myoldmopar Myoldmopar merged commit 68b3b1c into develop Jun 21, 2021
@Myoldmopar Myoldmopar deleted the replace-readitem-in-processnumber branch June 21, 2021 16:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Performance Includes code changes that are directed at improving the runtime performance of EnergyPlus Refactoring Includes code changes that don't change the functionality of the program, just perform refactoring
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants