-
Notifications
You must be signed in to change notification settings - Fork 0
Add rev11 profiler harness, focused rev14 aggregation optimization, and statistical validator #11
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,207 @@ | ||
| function results = profile_subchunk_agg_check_maxazi_rev11_real( ... | ||
| app, ... | ||
| cell_aas_dist_data, ... | ||
| array_bs_azi_data, ... | ||
| radar_beamwidth, ... | ||
| min_azimuth, ... | ||
| max_azimuth, ... | ||
| base_protection_pts, ... | ||
| point_idx, ... | ||
| on_list_bs, ... | ||
| cell_sim_chunk_idx, ... | ||
| rand_seed1, ... | ||
| agg_check_reliability, ... | ||
| on_full_Pr_dBm, ... | ||
| clutter_loss, ... | ||
| custom_antenna_pattern, ... | ||
| sub_point_idx) | ||
| %PROFILE_SUBCHUNK_AGG_CHECK_MAXAZI_REV11_REAL | ||
| % Profile rev11 on exact real inputs and report dominant runtime contributors. | ||
|
|
||
| if exist('subchunk_agg_check_maxazi_rev11','file')~=2 | ||
| error('profile_subchunk_agg_check_maxazi_rev11_real:MissingRev11', ... | ||
| 'subchunk_agg_check_maxazi_rev11.m was not found on MATLAB path.'); | ||
| end | ||
|
|
||
| opts = struct(); | ||
| opts.AziChunkRev11 = 128; | ||
| opts.TopN = 15; | ||
| opts.EnableDetailBuiltin = true; | ||
|
|
||
| fprintf('\n=== PROFILE REV11 (REAL INPUTS) ===\n'); | ||
| fprintf('AZI_CHUNK rev11: %d\n',opts.AziChunkRev11); | ||
|
|
||
| profile off; | ||
| profile clear; | ||
| if opts.EnableDetailBuiltin | ||
| profile('-memory','off','-detail','builtin'); | ||
| end | ||
| profile on; | ||
|
|
||
| runtime_tic=tic; | ||
| out = subchunk_agg_check_maxazi_rev11(app,cell_aas_dist_data,array_bs_azi_data, ... | ||
| radar_beamwidth,min_azimuth,max_azimuth,base_protection_pts,point_idx,on_list_bs, ... | ||
| cell_sim_chunk_idx,rand_seed1,agg_check_reliability,on_full_Pr_dBm,clutter_loss, ... | ||
| custom_antenna_pattern,sub_point_idx,opts.AziChunkRev11); %#ok<NASGU> | ||
| wall_runtime_s=toc(runtime_tic); | ||
|
|
||
| profile off; | ||
| pinfo=profile('info'); | ||
|
|
||
| if ~isfield(pinfo,'FunctionTable') || isempty(pinfo.FunctionTable) | ||
| error('profile_subchunk_agg_check_maxazi_rev11_real:EmptyProfile', ... | ||
| 'MATLAB profile did not return function timing data.'); | ||
| end | ||
|
|
||
| ft=pinfo.FunctionTable; | ||
| name_col=cell(numel(ft),1); | ||
| total_col=zeros(numel(ft),1); | ||
| self_col=zeros(numel(ft),1); | ||
| calls_col=zeros(numel(ft),1); | ||
| for i=1:numel(ft) | ||
| name_col{i}=safe_get(ft(i),{'FunctionName','CompleteName','FileName'},'<unknown>'); | ||
| total_col(i)=safe_get(ft(i),{'TotalTime'},NaN); | ||
| self_col(i)=safe_get(ft(i),{'SelfTime'},NaN); | ||
| calls_col(i)=safe_get(ft(i),{'NumCalls'},NaN); | ||
| end | ||
|
|
||
| tbl=table(name_col,total_col,self_col,calls_col, ... | ||
| 'VariableNames',{'Function','TotalTime_s','SelfTime_s','NumCalls'}); | ||
|
|
||
| [~,idx_total]=sort(tbl.TotalTime_s,'descend','MissingPlacement','last'); | ||
| [~,idx_self]=sort(tbl.SelfTime_s,'descend','MissingPlacement','last'); | ||
|
|
||
| top_n=min(opts.TopN,height(tbl)); | ||
| top_total=tbl(idx_total(1:top_n),:); | ||
| top_self=tbl(idx_self(1:top_n),:); | ||
|
|
||
| fprintf('\nTop contributors by total time:\n'); | ||
| disp(top_total); | ||
|
|
||
| fprintf('\nTop contributors by self time:\n'); | ||
| disp(top_self); | ||
|
|
||
| key_names = { ... | ||
| 'subchunk_agg_check_maxazi_rev11', ... | ||
| 'monte_carlo_Pr_dBm_rev2_app', ... | ||
| 'monte_carlo_super_bs_eirp_dist_rev5', ... | ||
| 'monte_carlo_clutter_rev3_app'}; | ||
|
|
||
| key_times = struct(); | ||
| for i=1:numel(key_names) | ||
| key=key_names{i}; | ||
| row=match_rows(tbl,key); | ||
| key_times.(matlab.lang.makeValidName(key))=summarize_rows(tbl,row,wall_runtime_s); | ||
| end | ||
|
|
||
| % Off-axis gain build path proxy: nearestpoint + azimuth contributions. | ||
| off_axis_parts={'nearestpoint_app','azimuth'}; | ||
| off_axis_rows=false(height(tbl),1); | ||
| for i=1:numel(off_axis_parts) | ||
| off_axis_rows=off_axis_rows | match_rows(tbl,off_axis_parts{i}); | ||
| end | ||
| off_axis_summary=summarize_rows(tbl,off_axis_rows,wall_runtime_s); | ||
|
|
||
| % Aggregation path proxy: db2pow/pow2db/sum/max inside rev11 aggregation loop. | ||
| agg_parts={'db2pow','pow2db','sum','max'}; | ||
| agg_rows=false(height(tbl),1); | ||
| for i=1:numel(agg_parts) | ||
| agg_rows=agg_rows | match_rows(tbl,agg_parts{i}); | ||
| end | ||
| agg_summary=summarize_rows(tbl,agg_rows,wall_runtime_s); | ||
|
|
||
| fprintf('\nExplicit target function timings:\n'); | ||
| print_key('subchunk_agg_check_maxazi_rev11',key_times.subchunk_agg_check_maxazi_rev11); | ||
| print_key('monte_carlo_Pr_dBm_rev2_app',key_times.monte_carlo_Pr_dBm_rev2_app); | ||
| print_key('monte_carlo_super_bs_eirp_dist_rev5',key_times.monte_carlo_super_bs_eirp_dist_rev5); | ||
| print_key('monte_carlo_clutter_rev3_app',key_times.monte_carlo_clutter_rev3_app); | ||
|
|
||
| fprintf('\nPath proxies (if visible in profiler):\n'); | ||
| print_key('off-axis gain build path proxy',off_axis_summary); | ||
| print_key('aggregation path proxy',agg_summary); | ||
|
|
||
| % Select highest-value optimization target from measured contributors. | ||
| focus_labels={ ... | ||
| 'aggregation_path_proxy', ... | ||
| 'monte_carlo_Pr_dBm_rev2_app', ... | ||
| 'monte_carlo_super_bs_eirp_dist_rev5', ... | ||
| 'monte_carlo_clutter_rev3_app', ... | ||
| 'off_axis_gain_build_proxy'}; | ||
| focus_times=[ ... | ||
| agg_summary.total_time_s, ... | ||
| key_times.monte_carlo_Pr_dBm_rev2_app.total_time_s, ... | ||
| key_times.monte_carlo_super_bs_eirp_dist_rev5.total_time_s, ... | ||
| key_times.monte_carlo_clutter_rev3_app.total_time_s, ... | ||
| off_axis_summary.total_time_s]; | ||
|
|
||
| [best_time,best_idx]=max(focus_times); | ||
| best_label=focus_labels{best_idx}; | ||
| if ~isfinite(best_time) || best_time<=0 | ||
| recommendation='Insufficient profiler signal; rerun with detail builtin enabled and larger workload.'; | ||
| else | ||
| recommendation=sprintf('Optimize %s first (largest measured contributor: %.6f s).',best_label,best_time); | ||
| end | ||
|
|
||
| fprintf('\nRecommendation: %s\n',recommendation); | ||
|
|
||
| results=struct(); | ||
| results.options=opts; | ||
| results.wall_runtime_s=wall_runtime_s; | ||
| results.top_by_total=top_total; | ||
| results.top_by_self=top_self; | ||
| results.key_timings=key_times; | ||
| results.off_axis_gain_build_path=off_axis_summary; | ||
| results.aggregation_path=agg_summary; | ||
| results.recommended_target=best_label; | ||
| results.recommendation_text=recommendation; | ||
| results.full_profile_table=tbl; | ||
|
|
||
| end | ||
|
|
||
| function val=safe_get(s,keys,default_val) | ||
| val=default_val; | ||
| for k=1:numel(keys) | ||
| if isfield(s,keys{k}) | ||
| val=s.(keys{k}); | ||
| return; | ||
| end | ||
| end | ||
| end | ||
|
|
||
| function rows=match_rows(tbl,pattern) | ||
| rows=false(height(tbl),1); | ||
| for i=1:height(tbl) | ||
| fn=tbl.Function{i}; | ||
| if contains(fn,pattern,'IgnoreCase',true) | ||
| rows(i)=true; | ||
| end | ||
| end | ||
| end | ||
|
|
||
| function s=summarize_rows(tbl,rows,wall_runtime_s) | ||
| if ~any(rows) | ||
| s=struct('visible',false,'num_rows',0,'total_time_s',0,'self_time_s',0, ... | ||
| 'pct_of_wall',0,'pct_of_profile_total',0,'calls',0,'matches',{{}}); | ||
| return; | ||
| end | ||
|
|
||
| total_profile_time=sum(tbl.TotalTime_s,'omitnan'); | ||
| s=struct(); | ||
| s.visible=true; | ||
| s.num_rows=nnz(rows); | ||
| s.total_time_s=sum(tbl.TotalTime_s(rows),'omitnan'); | ||
| s.self_time_s=sum(tbl.SelfTime_s(rows),'omitnan'); | ||
| s.pct_of_wall=100*s.total_time_s/max(wall_runtime_s,eps); | ||
| s.pct_of_profile_total=100*s.total_time_s/max(total_profile_time,eps); | ||
| s.calls=sum(tbl.NumCalls(rows),'omitnan'); | ||
| s.matches=tbl.Function(rows); | ||
| end | ||
|
|
||
| function print_key(label,s) | ||
| if s.visible | ||
| fprintf(' %-38s total=%10.6f s | self=%10.6f s | wall%%=%6.2f%% | calls=%g\n', ... | ||
| label,s.total_time_s,s.self_time_s,s.pct_of_wall,s.calls); | ||
| else | ||
| fprintf(' %-38s not visible in current profiler table\n',label); | ||
| end | ||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,120 @@ | ||
| function [sub_array_agg_check_mc_dBm]=subchunk_agg_check_maxazi_rev14(app,cell_aas_dist_data,array_bs_azi_data,radar_beamwidth,min_azimuth,max_azimuth,base_protection_pts,point_idx,on_list_bs,cell_sim_chunk_idx,rand_seed1,agg_check_reliability,on_full_Pr_dBm,clutter_loss,custom_antenna_pattern,sub_point_idx,varargin) | ||
| %SUBCHUNK_AGG_CHECK_MAXAZI_REV14 | ||
| % Focused optimization pass over rev11. | ||
| % Optimization target: aggregation path in STEP 4. | ||
| % Strategy: avoid repeated per-chunk db2pow/pow2db conversion over full BSxAZI matrix. | ||
| % Preserve rev11 RNG behavior and output contract. | ||
|
|
||
| AZI_CHUNK_DEFAULT=128; | ||
| DEBUG_CHECKS=false; | ||
| azi_chunk=AZI_CHUNK_DEFAULT; | ||
| if ~isempty(varargin) | ||
| azi_chunk=varargin{1}; | ||
| end | ||
| azi_chunk=max(1,round(azi_chunk)); | ||
|
|
||
| array_aas_dist_data=cell_aas_dist_data{2}; | ||
| aas_dist_azimuth=cell_aas_dist_data{1}; | ||
| mod_azi_diff_bs=array_bs_azi_data(:,4); | ||
|
|
||
| % Off-axis EIRP lookup at BS-relative azimuth. | ||
| nn_azi_idx=nearestpoint_app(app,mod_azi_diff_bs,aas_dist_azimuth); | ||
| super_array_bs_eirp_dist=array_aas_dist_data(nn_azi_idx,:); | ||
|
|
||
| % Simulation azimuth grid. | ||
| [array_sim_azimuth,num_sim_azi]=calc_sim_azimuths_rev3_360_azimuths_app(app,radar_beamwidth,min_azimuth,max_azimuth); | ||
|
|
||
| % BS->point azimuths. | ||
| sim_pt=base_protection_pts(point_idx,:); | ||
| bs_azimuth=azimuth(sim_pt(1),sim_pt(2),on_list_bs(:,1),on_list_bs(:,2)); | ||
|
|
||
| % MC iteration indices for this sub-point. | ||
| sub_mc_idx=cell_sim_chunk_idx{sub_point_idx}; %#ok<NASGU> | ||
| num_mc_idx=length(sub_mc_idx); | ||
| num_bs=length(bs_azimuth); | ||
| sub_array_agg_check_mc_dBm=NaN(num_mc_idx,1); | ||
|
|
||
| % ------------------------------------------------------------------------- | ||
| % STEP 1: MC random pre-generation using a single RNG seeding call. | ||
| % ------------------------------------------------------------------------- | ||
| rel_min=min(agg_check_reliability); | ||
| rel_max=max(agg_check_reliability); | ||
|
|
||
| if rel_min==rel_max | ||
| rand_pr_all=repmat(rel_min,num_bs,num_mc_idx); | ||
| rand_eirp_all=rand_pr_all; | ||
| rand_clutter_all=rand_pr_all; | ||
| else | ||
| rng(rand_seed1); | ||
| rel_span=(rel_max-rel_min); | ||
| rand_pr_all=rel_min+rel_span.*rand(num_bs,num_mc_idx); | ||
| rand_eirp_all=rel_min+rel_span.*rand(num_bs,num_mc_idx); | ||
| rand_clutter_all=rel_min+rel_span.*rand(num_bs,num_mc_idx); | ||
| end | ||
|
|
||
| % ------------------------------------------------------------------------- | ||
| % STEP 2: Precompute off-axis gain matrix once for all (bs,sim_azimuth). | ||
| % ------------------------------------------------------------------------- | ||
| pat_az=mod(custom_antenna_pattern(:,1),360); | ||
| pat_gain=custom_antenna_pattern(:,2); | ||
| [pat_az_unique,ia_unique]=unique(pat_az,'stable'); | ||
| pat_gain_unique=pat_gain(ia_unique); | ||
|
|
||
| off_axis_gain_matrix=NaN(num_bs,num_sim_azi); | ||
| for azimuth_idx=1:1:num_sim_azi | ||
| sim_azimuth=array_sim_azimuth(azimuth_idx); | ||
| rel_az=mod(bs_azimuth-sim_azimuth,360); | ||
| ant_deg_idx=nearestpoint_app(app,rel_az,pat_az_unique); | ||
| off_axis_gain_matrix(:,azimuth_idx)=pat_gain_unique(ant_deg_idx); | ||
| end | ||
|
|
||
| % Focused optimization input for STEP 4: | ||
| % convert off-axis gain once to multiplicative mW-domain factor. | ||
| off_axis_gain_linear=db2pow(off_axis_gain_matrix); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This line materializes a second full Useful? React with 👍 / 👎. |
||
|
|
||
| % ------------------------------------------------------------------------- | ||
| % STEP 3: RNG-free MC pathloss terms for each MC realization. | ||
| % ------------------------------------------------------------------------- | ||
| sort_monte_carlo_pr_dBm_all=NaN(num_bs,num_mc_idx); | ||
| for loop_idx=1:1:num_mc_idx | ||
| pre_sort_monte_carlo_pr_dBm=monte_carlo_Pr_dBm_rev2_app(app,agg_check_reliability,on_full_Pr_dBm,rand_pr_all(:,loop_idx)); | ||
| rand_norm_eirp=monte_carlo_super_bs_eirp_dist_rev5(app,super_array_bs_eirp_dist,agg_check_reliability,rand_eirp_all(:,loop_idx)); | ||
| monte_carlo_clutter_loss=monte_carlo_clutter_rev3_app(app,agg_check_reliability,clutter_loss,rand_clutter_all(:,loop_idx)); | ||
|
|
||
| sort_monte_carlo_pr_dBm_all(:,loop_idx)=pre_sort_monte_carlo_pr_dBm+rand_norm_eirp-monte_carlo_clutter_loss; | ||
| end | ||
|
|
||
| % ------------------------------------------------------------------------- | ||
| % STEP 4: Aggregate over BS in linear mW domain, max over azimuth. | ||
| % rev11 used db2pow(base+gain) inside each chunk; rev14 factors that as: | ||
| % 10^((base+gain)/10) = 10^(base/10) .* 10^(gain/10) | ||
| % so base conversion is once per MC realization and gain conversion is once globally. | ||
| % ------------------------------------------------------------------------- | ||
| for loop_idx=1:1:num_mc_idx | ||
| base_mc=sort_monte_carlo_pr_dBm_all(:,loop_idx); | ||
| base_mc_linear=db2pow(base_mc); % mW | ||
| max_azi_agg=-Inf; | ||
|
|
||
| for azi_start=1:azi_chunk:num_sim_azi | ||
| azi_end=min(azi_start+azi_chunk-1,num_sim_azi); | ||
| chunk_gain_linear=off_axis_gain_linear(:,azi_start:azi_end); | ||
|
|
||
| chunk_mW=sum(base_mc_linear.*chunk_gain_linear,1,'omitnan'); | ||
| azimuth_agg_dBm_chunk=pow2db(chunk_mW); | ||
|
|
||
| if DEBUG_CHECKS | ||
| if any(isnan(azimuth_agg_dBm_chunk),'all') | ||
| error('subchunk_agg_check_maxazi_rev14:NaNChunkAgg','NaN detected in chunk aggregate output'); | ||
| end | ||
| end | ||
|
|
||
| chunk_max=max(azimuth_agg_dBm_chunk,[],'omitnan'); | ||
| if chunk_max>max_azi_agg | ||
| max_azi_agg=chunk_max; | ||
| end | ||
| end | ||
|
|
||
| sub_array_agg_check_mc_dBm(loop_idx,1)=max_azi_agg; | ||
| end | ||
|
|
||
| end | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The aggregation proxy is built from substring matches and includes
'max', somatch_rowswill also capture unrelated functions likesubchunk_agg_check_maxazi_rev11(and any other name containingmax). This inflatesagg_summary.total_time_sand can biasrecommended_targettoward aggregation even when another helper is the true hotspot, which defeats the profiler harness’s goal of identifying the dominant bottleneck.Useful? React with 👍 / 👎.