adding explaination of volatile

This commit is contained in:
Jidong Xiao
2025-02-24 22:17:23 -05:00
committed by JamesFlare
parent f7f69ecd2f
commit 33c771a3a5

View File

@@ -11,27 +11,33 @@ $ sudo apt-get install binutils
## Compiling a C++ Program for Profiling ## Compiling a C++ Program for Profiling
To use `gprof`, compile your program with the `-pg` flag: To use `gprof`, compile your program with the `-pg` flag:
```sh ```sh
$ g++ -pg -o my_program my_program.cpp $ g++ -pg -o test test.cpp
``` ```
## Example C++ Program ## Example C++ Program
Create a file `my_program.cpp` with the following code: Create a file `test.cpp` with the following code:
```cpp ```cpp
#include <iostream> #include <iostream>
#include <chrono>
#include <thread>
void slowFunction() { void heavyComputation() {
std::this_thread::sleep_for(std::chrono::seconds(1)); volatile long long sum = 0;
for (long long i = 0; i < 500000000; ++i) {
sum += i; // Simple but expensive loop
}
} }
void fastFunction() { void lightComputation() {
for (volatile int i = 0; i < 1000000; ++i); volatile int sum = 0;
for (int i = 0; i < 100000; ++i) {
sum += i; // Lighter loop
}
} }
int main() { int main() {
for (int i = 0; i < 5; ++i) slowFunction(); heavyComputation(); // Call heavy function once
for (int i = 100; i < 200; ++i) fastFunction(); for (int i = 0; i < 1000; ++i) {
lightComputation(); // Call light function many times
}
return 0; return 0;
} }
``` ```
@@ -39,15 +45,15 @@ int main() {
## Running and Profiling the Program ## Running and Profiling the Program
1. Compile the program: 1. Compile the program:
```sh ```sh
$ g++ -pg -o my_program my_program.cpp $ g++ -pg -o test test.cpp
``` ```
2. Execute the program to generate `gmon.out`: 2. Execute the program to generate `gmon.out`:
```sh ```sh
$ ./my_program $ ./test
``` ```
3. Analyze the profiling data: 3. Analyze the profiling data:
```sh ```sh
$ gprof my_program gmon.out > profile.txt $ gprof test gmon.out > profile.txt
$ cat profile.txt $ cat profile.txt
``` ```
@@ -62,3 +68,54 @@ int main() {
## Conclusion ## Conclusion
`gprof` is a powerful tool for detecting performance bottlenecks in C++ programs. By identifying expensive functions, developers can make targeted optimizations. `gprof` is a powerful tool for detecting performance bottlenecks in C++ programs. By identifying expensive functions, developers can make targeted optimizations.
# Why Use `volatile` in the above program?
## Compiler May Remove the Loops
When compiling a program, the compiler applies optimizations to make the code run faster. One such optimization is **dead code elimination**, where the compiler removes code that does **not affect the program's observable behavior**.
For example, consider this function:
```cpp
void heavyComputation() {
long long sum = 0;
for (long long i = 0; i < 500000000; ++i) {
sum += i;
}
}
```
- The compiler notices that `sum` is **never used outside the function**.
- Since the result is discarded, the compiler **may completely remove the loop**.
- This means `heavyComputation()` might do **nothing** at runtime, which ruins our profiling experiment.
---
## How Does `volatile` Help?
Declaring a variable as `volatile` tells the compiler:
"This variable might change in ways you cannot predict, so do not optimize it away."
For example:
```cpp
void heavyComputation() {
volatile long long sum = 0; // Mark sum as volatile
for (long long i = 0; i < 500000000; ++i) {
sum += i;
}
}
```
- Now, **even if `sum` is never used**, the compiler **must** perform the loop.
- The `volatile` keyword prevents the compiler from assuming that `sum` is unimportant.
- This ensures that the loop actually runs during profiling.
---
## **Does `volatile` Affect Performance?**
Yes, but only slightly.
- **Without `volatile`**, the compiler can optimize the loop aggressively.
- **With `volatile`**, every read and write to `sum` is guaranteed to happen exactly as written, preventing some optimizations.
However, this small cost is **worth it for benchmarking**, because it ensures that the loops are not removed.