【测速】矩阵翻转

[size=large]在微博中看到有人分享了篇文章“为什么转置512×512矩阵,会比513×513矩阵慢很多?”[/size][url]http://note.sdo.com/u/1557869253/n/sSPb5~k5HYUMLX0mU000QX[/url]
[size=large]没仔细看原理,但与缓存的命中率有关。
今天写矩阵翻转的代码,突然想到这个问题。测了一下速度:[/size]
[color=red][size=xx-large]结论:[/size][/color][size=large]新建一片内存,顺序访问其中的元素,速度比较快!!!在翻转中能快个两倍左右!!!(注:我的矩阵是行优先存储的)[/size]


[color=red][size=xx-large]有关代码如下(代码不完全):[/size][/color]
	//水平翻转矩阵中的元素
void flipHorizontally(){
T tmp;
//int halfHeight=height_row/2;
int halfWidth=width_col/2;
for (int r=0; r<height_row; r++) {
for (int c=0; c<halfWidth; c++) {
int c2=width_col-1-c;
tmp=getValue(r,c);
this->operator()(r,c)=this->operator()(r,c2);
this->operator()(r,c2)=tmp;
}
}

}

//水平翻转矩阵中的元素
Matrix flipHorizontallyNewMatrix(){
Matrix flipped(height_row,width_col);
int halfWidth=width_col/2;
for (int r=0; r<height_row; r++) {
for (int c=0; c<=halfWidth; c++) {
int c2=width_col-1-c;
flipped(r,c)=this->operator()(r,c2);
flipped(r,c2)=this->operator()(r,c);
}
}
return flipped;
}

//水平翻转矩阵中的元素
Matrix flipHorizontallyNewMatrix2(){
Matrix flipped(height_row,width_col);
for (int r=0; r<height_row; r++) {
for (int c=0; c<width_col; c++) {
int c2=width_col-1-c;
flipped(r,c)=this->operator()(r,c2);
}
}
return flipped;
}


//垂直翻转矩阵中的元素
Matrix flipVerticallyNewMatrix(){
Matrix flipped(height_row,width_col);
int halfHeight=height_row/2;
for (int r=0; r<=halfHeight; r++) {
for (int c=0; c<width_col; c++) {
int r2=height_row-1-r;
flipped(r,c)=this->operator()(r2,c);
flipped(r2,c)=this->operator()(r,c);
}
}
return flipped;
}

//垂直翻转矩阵中的元素
Matrix flipVerticallyNewMatrix2(){
Matrix flipped(height_row,width_col);
for (int r=0; r<height_row; r++) {
for (int c=0; c<width_col; c++) {
int r2=height_row-1-r;
flipped(r,c)=this->operator()(r2,c);
//flipped(r2,c)=this->operator()(r,c);
}
}
return flipped;
}


//垂直翻转矩阵中的元素
void flipVertically(){
T tmp;
int halfHeight=height_row/2;
for (int r=0; r<halfHeight; r++) {
for (int c=0; c<width_col; c++) {
int r2=height_row-1-r;
tmp=getValue(r,c);
this->operator()(r,c)=this->operator()(r2,c);
this->operator()(r2,c)=tmp;
}
}

}



[color=red][size=xx-large]测试用的代码如下(代码不完全):[/size][/color]

for (int n=10; n<1000; n+=33) {


MatrixInt m(n,n);
for (int i=0; i<m.getNumEl(); i++) {
m(i)=i;
}

int testNum=10000/n*10000/n;
Timer timer;

for(int i=0; i<testNum; i++)
m.flipVerticallyNewMatrix();
long tv1=timer.getElapsedTimeAndRestart();

for(int i=0; i<testNum; i++)
m.flipVerticallyNewMatrix2();
long tv2=timer.getElapsedTimeAndRestart();

for(int i=0; i<testNum; i++)
m.flipVertically();
long tvInplace=timer.getElapsedTimeAndRestart();

for(int i=0; i<testNum; i++)
m.flipHorizontallyNewMatrix();
long th1=timer.getElapsedTimeAndRestart();

for(int i=0; i<testNum; i++)
m.flipHorizontallyNewMatrix2();
long th2=timer.getElapsedTimeAndRestart();

for(int i=0; i<testNum; i++)
m.flipHorizontally();
long thInplace=timer.getElapsedTimeAndRestart();
cout<<"矩阵大小: "<<m.height_row<<"行*"<<m.width_col<<"列"<<endl;
cout<<"水平翻转耗时:方法1: "<<th1<<";\t\t方法2: "<<th2<<";\t\t原位翻转: "<<thInplace<<endl;
cout<<"垂直翻转耗时:方法1: "<<tv1<<";\t\t方法2: "<<tv2<<";\t\t原位翻转: "<<tvInplace<<endl;
cout<<endl;

}



[color=red][size=xx-large]测试用结果如下:[/size][/color]
矩阵大小: 10行*10列
水平翻转耗时:方法1: 566; 方法2: 340; 原位翻转: 410
垂直翻转耗时:方法1: 652; 方法2: 342; 原位翻转: 450

矩阵大小: 43行*43列
水平翻转耗时:方法1: 364; 方法2: 180; 原位翻转: 390
垂直翻转耗时:方法1: 425; 方法2: 178; 原位翻转: 434

矩阵大小: 76行*76列
水平翻转耗时:方法1: 361; 方法2: 188; 原位翻转: 402
垂直翻转耗时:方法1: 433; 方法2: 183; 原位翻转: 445

矩阵大小: 109行*109列
水平翻转耗时:方法1: 360; 方法2: 180; 原位翻转: 397
垂直翻转耗时:方法1: 411; 方法2: 174; 原位翻转: 440

矩阵大小: 142行*142列
水平翻转耗时:方法1: 357; 方法2: 176; 原位翻转: 406
垂直翻转耗时:方法1: 413; 方法2: 173; 原位翻转: 456

矩阵大小: 175行*175列
水平翻转耗时:方法1: 353; 方法2: 173; 原位翻转: 403
垂直翻转耗时:方法1: 412; 方法2: 171; 原位翻转: 452

矩阵大小: 208行*208列
水平翻转耗时:方法1: 359; 方法2: 176; 原位翻转: 408
垂直翻转耗时:方法1: 417; 方法2: 173; 原位翻转: 455

矩阵大小: 241行*241列
水平翻转耗时:方法1: 349; 方法2: 171; 原位翻转: 400
垂直翻转耗时:方法1: 411; 方法2: 170; 原位翻转: 449

矩阵大小: 274行*274列
水平翻转耗时:方法1: 346; 方法2: 173; 原位翻转: 400
垂直翻转耗时:方法1: 406; 方法2: 167; 原位翻转: 448

矩阵大小: 307行*307列
水平翻转耗时:方法1: 343; 方法2: 170; 原位翻转: 400
垂直翻转耗时:方法1: 402; 方法2: 168; 原位翻转: 443

矩阵大小: 340行*340列
水平翻转耗时:方法1: 360; 方法2: 174; 原位翻转: 420
垂直翻转耗时:方法1: 410; 方法2: 169; 原位翻转: 447

矩阵大小: 373行*373列
水平翻转耗时:方法1: 460; 方法2: 259; 原位翻转: 398
垂直翻转耗时:方法1: 512; 方法2: 261; 原位翻转: 443

矩阵大小: 406行*406列
水平翻转耗时:方法1: 456; 方法2: 262; 原位翻转: 403
垂直翻转耗时:方法1: 516; 方法2: 255; 原位翻转: 452

矩阵大小: 439行*439列
水平翻转耗时:方法1: 450; 方法2: 248; 原位翻转: 401
垂直翻转耗时:方法1: 500; 方法2: 249; 原位翻转: 445

矩阵大小: 472行*472列
水平翻转耗时:方法1: 453; 方法2: 269; 原位翻转: 402
垂直翻转耗时:方法1: 513; 方法2: 265; 原位翻转: 450

矩阵大小: 505行*505列
水平翻转耗时:方法1: 433; 方法2: 252; 原位翻转: 390
垂直翻转耗时:方法1: 489; 方法2: 249; 原位翻转: 436

矩阵大小: 538行*538列
水平翻转耗时:方法1: 440; 方法2: 247; 原位翻转: 398
垂直翻转耗时:方法1: 497; 方法2: 247; 原位翻转: 444

矩阵大小: 571行*571列
水平翻转耗时:方法1: 443; 方法2: 256; 原位翻转: 397
垂直翻转耗时:方法1: 496; 方法2: 248; 原位翻转: 440

矩阵大小: 604行*604列
水平翻转耗时:方法1: 439; 方法2: 252; 原位翻转: 402
垂直翻转耗时:方法1: 494; 方法2: 248; 原位翻转: 438

矩阵大小: 637行*637列
水平翻转耗时:方法1: 436; 方法2: 244; 原位翻转: 397
垂直翻转耗时:方法1: 488; 方法2: 242; 原位翻转: 432

矩阵大小: 670行*670列
水平翻转耗时:方法1: 427; 方法2: 243; 原位翻转: 384
垂直翻转耗时:方法1: 483; 方法2: 238; 原位翻转: 427

矩阵大小: 703行*703列
水平翻转耗时:方法1: 449; 方法2: 257; 原位翻转: 403
垂直翻转耗时:方法1: 527; 方法2: 260; 原位翻转: 459

矩阵大小: 736行*736列
水平翻转耗时:方法1: 432; 方法2: 246; 原位翻转: 395
垂直翻转耗时:方法1: 493; 方法2: 245; 原位翻转: 440

矩阵大小: 769行*769列
水平翻转耗时:方法1: 452; 方法2: 258; 原位翻转: 409
垂直翻转耗时:方法1: 518; 方法2: 256; 原位翻转: 458

矩阵大小: 802行*802列
水平翻转耗时:方法1: 434; 方法2: 248; 原位翻转: 392
垂直翻转耗时:方法1: 492; 方法2: 248; 原位翻转: 433

矩阵大小: 835行*835列
水平翻转耗时:方法1: 415; 方法2: 240; 原位翻转: 372
垂直翻转耗时:方法1: 466; 方法2: 234; 原位翻转: 416

矩阵大小: 868行*868列
水平翻转耗时:方法1: 427; 方法2: 247; 原位翻转: 388
垂直翻转耗时:方法1: 478; 方法2: 239; 原位翻转: 433

矩阵大小: 901行*901列
水平翻转耗时:方法1: 448; 方法2: 262; 原位翻转: 400
垂直翻转耗时:方法1: 499; 方法2: 251; 原位翻转: 449

矩阵大小: 934行*934列
水平翻转耗时:方法1: 422; 方法2: 248; 原位翻转: 380
垂直翻转耗时:方法1: 477; 方法2: 237; 原位翻转: 426

矩阵大小: 967行*967列
水平翻转耗时:方法1: 436; 方法2: 257; 原位翻转: 388
垂直翻转耗时:方法1: 493; 方法2: 248; 原位翻转: 438
%% 参数设置 c = 3e8; % 光速 [m/s] B = 500e6; % 带宽 500MHz Tc = 100e-6; % 调频周期 100μs Fs = 30e6; % 采样率 30MHz N_pulses = 128; % 脉冲数(用于测速) F0 = 24e9; % 载频 24GHz lambda = c/F0; % 波长 N = round(Tc*Fs); % 单个脉冲采样点数 t = (0:N-1)/Fs; % 单个脉冲时间向量 S = B/(Tc/2); % 调频斜率修正 PRI = Tc; % 脉冲重复间隔 %% 目标参数(四个目标:两个真实、两个虚像) targets = [... 50, 10, 1.0; % 真实目标1: 距离100m, 速度15m/s, RCS=1.0 55, 2.8, 1.0; % 真实目标2: 距离150m, 速度-10m/s, RCS=0.8 40, 5, 0.6; % 虚像1: 距离60m, 速度25m/s, RCS=0.6 64, -8, 0.5 % 虚像2: 距离180m, 速度-20m/s, RCS=0.5 ]; %% 窗函数配置(修正维度问题) range_win = hamming(N)'; % 距离维窗(行向量:1×N) doppler_win = hamming(N_pulses); % 速度维窗(列向量:N_pulses×1) win_corr_range = sum(range_win)/N; win_corr_doppler = sum(doppler_win)/N_pulses; %% 发射信号生成 Tx_freq = zeros(1, N); Tx_freq(t <= Tc/2) = S * t(t <= Tc/2); Tx_freq(t > Tc/2) = B - S*(t(t > Tc/2) - Tc/2); phase_tx = 2*pi*cumsum(Tx_freq)/Fs; % 相位积分 Tx_pulse = exp(1j*phase_tx); Tx_signal = repmat(Tx_pulse, N_pulses, 1); % N_pulses×N矩阵 %% 接收信号生成(多目标处理) Rx_signals = zeros(N_pulses, N); % 预分配接收信号矩阵 for pulse_idx = 1:N_pulses rx_pulse = zeros(1, N); % 当前脉冲的回波信号 current_time_offset = (pulse_idx - 1) * PRI; % 处理每个目标 for target_idx = 1:size(targets, 1) dist = targets(target_idx, 1); vel = targets(target_idx, 2); rcs = targets(target_idx, 3); current_dist = dist + vel * current_time_offset; td = 2 * current_dist / c; delay_samples = round(td * Fs); % 确保延迟在合理范围内 if delay_samples >= N delay_samples = N - 1; elseif delay_samples < 0 delay_samples = 0; end % 多普勒相位计算 doppler_phase = exp(1j * 4 * pi * vel * F0 * current_time_offset / c); % 生成时延信号 delayed_tx = [zeros(1, delay_samples), Tx_pulse(1:end-delay_samples)]; % 叠加当前目标的回波信号 rx_pulse = rx_pulse + sqrt(rcs) * delayed_tx * doppler_phase; end Rx_signals(pulse_idx, :) = rx_pulse; end %% 差频信号处理(修正维度问题) IF_signals = Tx_signal .* conj(Rx_signals); % 混频得到差频信号 % 距离维加窗处理(修正维度) IF_windowed_range = IF_signals .* repmat(range_win, N_pulses, 1); % 应用距离窗 range_fft = fft(IF_windowed_range, [], 2); % 对距离维做FFT(保持原始顺序) % 速度维加窗处理(修正维度) IF_windowed_doppler = range_fft .* repmat(doppler_win, 1, N); % 应用速度窗 doppler_fft = fft(IF_windowed_doppler, [], 1); % 对速度维做FFT % FFT移位和幅度校正 range_fft = fftshift(range_fft, 2)/win_corr_range; % 距离维移位 doppler_fft = fftshift(doppler_fft, 1)/win_corr_doppler; % 速度维移位 %% 坐标轴生成(修正计算) % 距离轴 range_bins = linspace(-Fs/2, Fs/2, N); % 频率轴 range_axis = range_bins * c/(2*S); % 转换为距离轴 max_range = c/(2*S) * Fs/2; % 最大显示距离 % 速度轴 doppler_bins = linspace(-1/(2*PRI), 1/(2*PRI), N_pulses); % 多普勒频率轴 velocity_axis = doppler_bins * lambda/2; % 转换为速度轴 max_velocity = lambda/(4*PRI); % 最大无模糊速度 %% 目标检测与虚像识别(改进算法) magnitude_spectrum = abs(doppler_fft); detected_targets = []; % 查找所有显著峰值 threshold = 0.05 * max(magnitude_spectrum(:)); % 动态阈值 [peak_rows, peak_cols] = find(magnitude_spectrum > threshold); % 处理检测到的每个峰值 for idx = 1:length(peak_rows) r_idx = peak_rows(idx); d_idx = peak_cols(idx); dist_val = range_axis(d_idx); vel_val = velocity_axis(r_idx); amp_val = magnitude_spectrum(r_idx, d_idx); % 排除边界附近的假目标 if abs(dist_val) > max_range*0.9 || abs(vel_val) > max_velocity*0.9 continue; end % 虚像检测标准:1.速度接近最大速度 2.幅度异常低 3.距离位置异常 is_ghost = (abs(vel_val) > max_velocity*0.8) || ... % 速度接近极限 (amp_val < threshold*5) || ... % 幅度过低 (dist_val < 10 || dist_val > 190); % 距离边缘异常 detected_targets = [detected_targets; dist_val, vel_val, amp_val, is_ghost]; end %% 绘制结果(优化显示) figure('Position', [100, 100, 1400, 800]); % 1. 距离-速度二维谱图 subplot(2, 2, [1, 3]); imagesc(velocity_axis, range_axis, 20*log10(abs(doppler_fft'))); xlabel('速度 (m/s)'); ylabel('距离 (m)'); title('距离-速度二维谱 (RD谱)'); axis xy; colorbar; colormap(jet); caxis([-50, 0]); % 设置动态范围 grid on; xlim([-35, 35]); ylim([0, 200]); % 标记目标位置 hold on; for i = 1:size(detected_targets, 1) if detected_targets(i, 4) % 虚像 plot(detected_targets(i,2), detected_targets(i,1), 'rx', 'MarkerSize', 12, 'LineWidth', 2); else % 真实目标 plot(detected_targets(i,2), detected_targets(i,1), 'go', 'MarkerSize', 12, 'LineWidth', 2); end end hold off; legend('虚像目标', '真实目标', 'Location', 'northwest'); % 2. 距离维度剖面 subplot(2, 2, 2); range_profile = sum(abs(doppler_fft), 1); plot(range_axis, 20*log10(range_profile)); xlabel('距离 (m)'); ylabel('幅度 (dB)'); title('距离剖面'); xlim([0, 200]); grid on; 分析代码中存在的问题,注:生成的rd谱存在严重错误,补全代码
最新发布
09-17
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值