Jo recurring maths tools yahan use honge, unhe ek baar plain words mein naam dena zaroori hai — har symbol defined ho, har unit stated ho — taaki koi bhi problem unhe use kare usse pehle.
(a) gprof — -pg flag compiler ko mcount() counter weave in karne par majboor karta hai, jo instrumentation hai (exact call counts, lekin timing change ho jaati hai).
(b) Callgrind (ek Valgrind tool) — poora program ek simulated CPU par execute hota hai, toh counts deterministic hain lekin yeh 20–100× slower chalata hai.
(c) perf — event-based sampling real PMU counters se driven, ~1–5% overhead.
Recall Solution
Sirf gprof strictly recompile maangta hai (tumhe -pg add karna hi hoga).
perf existing binary par kaam karta hai (-g aur -fno-omit-frame-pointer add karna sirf symbol/call-graph quality improve karta hai).
Callgrind ko bhi koi recompile nahi chahiye — woh binary ko run time par Valgrind VM ke through instrument karta hai. -g add karna sirf nicer source-line attribution deta hai.
Recall Solution
main ka total time = uska apna body plus jo bhi woh call karta hai. Near-zero self time ka matlab hai main khud almost kuch nahi karta — uska bada total sirf uske children ka sum hai.
main ko optimize mat karo. Tum self time se optimize karte ho (jahan CPU actually baithta hai); total time sirf ek expensive subtree dhundhne ke liye hai jisme drill in karna ho.
(a) Har sample wall time ka Δt=10ms=0.010s "represent" karta hai. Total run time =NΔt=5000×0.010s=50s.
(b) Function ka owned fraction =nf/N=1500/5000=0.30. Toh
Tself=NnfTtotal=0.30×50s=15s,
jo sirf nfΔt=1500×0.010=15s bhi hai. Dono routes agree karte hain, jaisa hona chahiye.
Recall Solution
Per-call cost =1063.60s=3.6×10−6s=3.6μs.
Itne bade call count ke saath, pehla sawaal "har call ko faster banao" nahi balki "kya main fewer calls kar sakta hoon?" hai — repeated inputs ko memoize karo, call ko loop se hoist karo, ya vectorize karo. Calls ko 106 se reduce karna poore 3.60 s par attack karta hai, jabki har call ko chip karna sirf constant par kaam karta hai.
Recall Solution
IPC = Instructions Per Cycle, core har clock tick mein kitni instructions finish karta hai:
IPC=cyclesinstructions=3.0×10109.0×109=0.30.CPI = Cycles Per Instruction, exact inverse — har instruction average par kitne clock ticks cost karti hai:
CPI=IPC1=0.301≈3.33.
IPC of 0.30 is far below the ~4 ceiling (equivalently CPI 3.33 matlab har instruction 3 se zyada cycles kheenchti hai), toh core zyaadatar cycles stalling mein spend karta hai (idle, waiting). Yeh memory ya branch problems point karta hai — L3 dekho — na ki ek cleverer algorithm ki zaroorat hai.
(a)s→∞ lene par: term p/s→0, toh
Speedupmax=1−p1=0.281≈3.57×.
No matter what, untouched 28% tumhe 3.57× par cap kar deta hai.
(b)s=4 ke saath:
Speedup=(1−0.72)+40.721=0.28+0.181=0.461≈2.17×.
Toh ek 4× local win ek 2.17× global win deta hai — 3.57× ceiling se kaafi kam, jo batata hai ki is ek function par aur effort ke sharply diminishing returns hain.
Recall Solution
cache miss rate=1.5×1091.8×108=0.12=12%.branch miss rate=2.0×1092.0×107=0.01=1%.
Branch predictor theek kaam kar raha hai (1%). 12% cache miss rate culprit hai: ek DRAM miss ~100+ cycles cost karta hai vs L1 hit ke ~4 cycles, toh woh misses low IPC easily explain kar dete hain. Fix Cache Hierarchy & Locality of Reference mein rehta hai — locality improve karo (struct-of-arrays, loop blocking) — na ki algorithmic complexity mein. Branch Prediction & Pipelining se compare karo, jo yahan problem nahi hai.
Recall Solution
Misses se lost cycles ≈1.8×108×120=2.16×1010 cycles.
Sab cycles ka fraction =3.0×10102.16×1010=0.72=72%.
~72% cycles plausibly memory stalls se consume ho rahe hain, toh cache behaviour akele slowdown ki vast majority account karta hai — memory waqai ek sufficient explanation hai, aur locality work sahi lever hai. Neeche di gayi figure yeh arithmetic cycle budget kaahan jaata hai iska picture banati hai.
(a) Callgrind — yeh deterministic hai (same input → identical instruction counts), toh ek >2% threshold machines across stable hai bina kisi timer noise ke. Slowness (20–100×) CI mein acceptable hai.
(b) gprof — quick aur classic; ek -pg rebuild plus ek command ek flat profile deta hai jo "roughly kaun sa function" ke liye kaafi hai.
(c) perf — real PMU hardware counters ~1–5% overhead par, release binary ka koi recompile nahi, aur yeh real CPU par true cache misses report karta hai. Callgrind disqualify hai kyunki uska simulated timing real-hardware timing nahi hai.
Recall Solution
(a)p=nf/N=2000/4000=0.50. (Sanity: NΔt=4000×0.010=40 s ✓ stated run se match karta hai.)
(b)Speedup=(1−0.5)+30.51=0.5+0.161=0.661=1.5×.(c) Naya time =1.540s≈26.7s.
Yeh forecast-then-verify discipline hai: edit karne se pehle26.7 s predict karo, phir confirm karne ke liye re-profile karo — agar measured time 26.7 s ke paas nahi hai, toh tumhara model (ya tumhari assumption ki sirf serialize badla) galat hai. Dekho Benchmarking & Microbenchmark Pitfalls.
Recall Solution
Har candidate par Amdahl formula alag apply karo.
A (pA=0.50, sA=1.6):
SpeedupA=(1−0.50)+1.60.501=0.50+0.31251=0.81251≈1.231×.B (pB=0.30, sB=5):
SpeedupB=(1−0.30)+50.301=0.70+0.061=0.761≈1.316×.B choose karo (1.316×>1.231×). Lesson: ek chota slice ek bade achievable speedup ke saath ek bade slice ko beat kar sakta hai jise tum mushkil se improve kar sako — Amdahl p/s shrink hone se reward karta hai, toh paurs dono matter karte hain, sirf p nahi.
-O2 par optimizer ne tiny_helper ko uske callers mein inline kar diya (dekho Compiler Optimization Flags (-O2, -O3, inlining)). Ek baar inline hone par, woh ek distinct function nahi raha jiske paas ek entry point ho, toh gprof ka mcount()/sample attribution usse time pin karne ki koi jagah nahi tha — uska cost ab caller ke self time mein fused ho gaya hai. Tumhara -O0 profile us code ki taraf point kar raha tha jo shipped binary mein exist hi nahi karta.
Sahi method: wahi optimization level profile karo jo tum ship karte ho (-O2/-O3), source symbols ke liye -g add karo, aur -fno-omit-frame-pointer taaki perf abhi bhi call graphs build kar sake. Kabhi -O0 profile se conclusions mat nikalo.
Callgrind instructions executed count karta hai: f few instructions chalata hai (8%).
Lekin perf dikhata hai f 90% cache misses trigger karta hai; har miss core ko ~100+ cycles stall karta hai bina kisi instructions ke, IPC ko 0.4 tak crush karta hai.
gprof wall-clock self time measure karta hai, jismein woh stall cycles bhi hain, toh f few instructions ke bawajood real time ka 40% khaata hai.
Coherent story:fmemory-bound hai — instructions mein cheap, time mein expensive kyunki woh DRAM ka intezaar karta hai. Yahi wajah hai ki mistake "Callgrind real seconds batata hai" dangerous hai: low instruction count ne ek real-time hog chhupaaya. Yahan timing truth ke liye perf use karo.
Recall Solution
(a)q^=ng/N=40/400=0.10 (10%).
(b)σq^=Nq^(1−q^)=4000.10×0.90=4000.09=2.25×10−4=0.015.
Toh q^±2σq^=0.10±0.03, yaani true fraction plausibly [0.07,0.13] mein hai. (Pehle normal-approximation conditions check karo: Nq^=40≥5 aur N(1−q^)=360≥5, toh bell-curve interval yahan trustworthy hai.)
(c) Poora interval 5% se upar baitha hai, toh pessimistic end par bhi g budget exceed karta hai — N=400 yeh conclude karne ke liye enough hai "over budget". Agar interval 5% ke aas paas hota toh tum longer run karte: σq^1/N ki tarah girta hai, toh error halve karne ke liye tumhe 4× samples chahiye. Isliye short profiling runs jittery hot-lists dete hain.
Recall Solution
(a) Instruction count fixed hone par, q ka run time ∝ cycles =instructions/IPC, toh q ka speedup =IPColdIPCnew=0.352.8=8×.
(b)Speedup=(1−0.60)+80.601=0.40+0.0751=0.4751≈2.11×.(c) Rewrite ke baad, perf re-run karo aur confirm karo ki q ka measured self time waqai ~8× drop kiya (equivalently uske cycles/miss-rate ne model ke anusaar giraavat dekhi). Agar whole-program speedup 2.11× ke paas nahi aaya, toh ya toh IPC 2.8 tak nahi pahuncha ya koi aur function naya bottleneck ban gaya — dobara profile karo. Yeh measure → model → change → re-measure loop close karta hai.
Recall Quick self-quiz (cloze)
Amdahl's speedup formula ::: Speedup=1/((1−p)+p/s)
Self time from samples ::: Tself=(nf/N)Ttotal=nfΔt
Standard deviation of a sampled fraction ::: σq^=q^(1−q^)/N
IPC of 0.3 on a 4-wide core ka matlab CPU mostly ::: stalling (waiting) hai, likely cache misses par
CPI kya stand karta hai aur kya equal hai? ::: Cycles Per Instruction, =1/IPC
Deterministic, machine-independent counts wala tool ::: Callgrind
Real hardware par ~1–5% overhead wala tool ::: perf
Tum kaun se time column se optimize karte ho, total se nahi? ::: self time