In recent 3 months, I did improve several applications performance tuning, gained much reduced memory usage and CPU time. Model training time takes from days to hours. Well, it is hard to achieve such success.
Minimal Runtime Environment
There are many small scripts and C++ applications during model training. Finding the most time consuming application to tune is easy since model training users can give a directly, correct feedback: which step takes a lot of time. Then review source code of that model training step. That step may contains several scripts and compiled applications. Which one take the most of the time? Users can show you via Task Manager (in windows) or top (linux).
What next is to prepare minimal runtime environment. It may be difficult since there are many trivial things (environment variables, config files, input data). Performance tune is not a one hammer done job, application to-tuned will be run many times. Minimal runtime environment let you focus on one application, easy to reproduce and verify.
Profile: Finding Bottleneck
With minimal runtime environment, use profiler to find bottleneck, like perf. To profile memory usage, use heaptrack to collect memory allocate/free operations.
Different languages have different official profile solutions. All of them generates similar results (CPU profiling). Such profile reports tell you where the bottleneck functions are.
For short but running slow python script, there is another way to find bottleneck. During python script running, press CTRL+C to stop running, python will print out stacks on stop time. Try several times, if printed stacks are same, you know the slow code is.
Pay attention to python slice in operation: item in slice. If length of slice is larger than 1000, it is really slow. Use set or dict, performance is constant with whatever size of input data.
Make It Correct, Then Make It Fast
Once finding the bottleneck functions, it is far from changing code to improve performance. You should answer the question: How can I prove the changes generate the same result?
Know It Well
Associate with input data and configuration, make sure you full understand the application source code.
- Application architecture, how source code layered, how components initialized.
- Data flow: where input data and configuration used and where generated the output.
- No need to look into every line of source code, draw an outline of functions call hierarchy.
- Finally, make sure fully understand every single line of source code of bottle-neck functions needed to be tuned.
Unit Test
If there are unit tests, you get luck. Keep unit tests running passed. Add new unit tests for your changes and it also make better unit test coverage.
In most of cases, there is no unit tests at all. Well it is your choice whether to add unit tests. If you do, it is a tough choice and keep your manager know there are much extra efforts:
- Import unit test library
- Add unit test step in CI build script (important, keep it running on every commit)
- More source code changes to make sure unit test stable (dependencies decouple)
If there is no nearby deadline, it is recommended to do such tough choices. Like someone said: It is difficult for one generation, but good harvest for next generations.
Sample Expected Result
With prepared input data and configuration, expected result data can be generated. Make sure you can easy to compare two result data to tell that they the equal. Sometime, result data is huge.
- md5 checksum. If result data should be strictly equal in bit data.
- diff: Good for small and text results.
- custom script: JSON file with different field orders. Float number data equality.
Inspiration
Some times it is hard to think out a better way or right way to improve performance. There may be several solutions out of your mind and you will deny them one by one after double thinking.
- If new solution has more steps, it is likely a worse solution.
- The more you learn the business model of source code, the more you find hidden or forgotten requirements. It helps making correct decision.
- More failures you make, much near to final success. Don’t give up.
- It is not always be succeed, put the tuning down for some time, it is just not the right time for you to resolve yet.
- As tuning problem and source code keep thinking over, the God will give you a silver lighting. And you know it, then miracle happens.
- Keep communicating with others, especially users or architectures, some legacy requirements can be dropped. It is another God’s gift to bright way to succeed.
During the whole process, you may fell lonely, like a single boat in the middle of ocean. Nobody helps you. And nobody cares whether your boat can arrived at beach(Although applications does not having good performance, the world is still turning.).
Don’t give up!
Don’t give up!
Don’t give up!