谱本征正交分解 (SPOD)附matlab代码

article/2025/9/1 18:26:23

✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。

🍎个人主页:Matlab科研工作室

🍊个人信条:格物致知。

更多Matlab仿真内容点击👇

智能优化算法  神经网络预测 雷达通信  无线传感器

信号处理 图像处理 路径规划 元胞自动机 无人机  电力系统

⛄ 内容介绍

SPOD() 是频域形式的本征正交分解(POD,也称为主成分分析或 Karhunen-Loève 分解)的 Matlab 实现,称为谱本征正交分解 (SPOD)。SPOD 源自固定流 [1,2] 的时空 POD 问题,并导致每个模式都以单一频率振荡。SPOD 模式代表动态结构,可以最佳地解释平稳随机过程的统计变异性。

⛄ 部分代码

function [L,P,f,Lc,A] = spod(X,varargin)

%SPOD Spectral proper orthogonal decomposition

%   [L,P,F] = SPOD(X) returns the spectral proper orthogonal decomposition

%   of the data matrix X whose first dimension is time. X can have any

%   number of additional spatial dimensions or variable indices. The

%   columns of L contain the modal energy spectra. P contains the SPOD

%   modes whose spatial dimensions are identical to those of X. The first

%   index of P is the frequency and the last one the mode number ranked in

%   descending order by modal energy. F is the frequency vector. If DT is

%   not specified, a unit frequency sampling is assumed. For real-valued

%   data, adjusted one-sided eigenvalue spectra are returned. Although

%   SPOD(X) automatically chooses default spectral estimation parameters,

%   the user is encouraged to manually specify problem-dependent parameters

%   on a case-to-case basis.

%

%   [L,P,F] = SPOD(X,WINDOW) uses a temporal window. If WINDOW is a vector,

%   X is divided into segments of the same length as WINDOW. Each segment

%   is then weighted (pointwise multiplied) by WINDOW. If WINDOW is a

%   scalar, a Hamming window of length WINDOW is used. If WINDOW is omitted

%   or set as empty, a Hamming window is used. Multitaper-Welch estimates

%   are computed with the syntax SPOD(X,[NFFT BW],...), where WINDOW is an

%   array of two scalars. NFFT is the window length and BW the

%   time-halfbandwidth product. See [4] for details. By default, a number

%   of FLOOR(2*BW)-1 discrete prolate spheroidal sequences (DPSS) is used

%   as tapers. Custom tapers can be specified in a column matrix of tapers

%   as WINDOW.

%

%   [L,P,F] = SPOD(X,WINDOW,WEIGHT) uses a spatial inner product weight in

%   which the SPOD modes are optimally ranked and orthogonal at each

%   frequency. WEIGHT must have the same spatial dimensions as X. 

%

%   [L,P,F] = SPOD(X,WINDOW,WEIGHT,NOVERLAP) increases the number of

%   segments by overlapping consecutive blocks by NOVERLAP snapshots.

%   NOVERLAP defaults to 50% of the length of WINDOW if not specified. 

%

%   [L,P,F] = SPOD(X,WINDOW,WEIGHT,NOVERLAP,DT) uses the time step DT

%   between consecutive snapshots to determine a physical frequency F. 

%

%   [L,P,F] = SPOD(XFUN,...,OPTS) accepts a function handle XFUN that

%   provides the i-th snapshot as x(i) = XFUN(i). Like the data matrix X,

%   x(i) can have any dimension. It is recommended to specify the total

%   number of snaphots in OPTS.nt (see below). If not specified, OPTS.nt

%   defaults to 10000. OPTS.isreal should be specified if a two-sided

%   spectrum is desired even though the data is real-valued, or if the data

%   is initially real-valued, but complex-valued for later snaphots.

%

%   [L,P,F] = SPOD(X,WINDOW,WEIGHT,NOVERLAP,DT,OPTS) specifies options:

%   OPTS.savefft: save FFT blocks to avoid storing all data in memory [{false} | true]

%   OPTS.deletefft: delete FFT blocks after calculation is completed [{true} | false]

%   OPTS.savedir: directory where FFT blocks and results are saved [ string | {'results'}]

%   OPTS.savefreqs: save results for specified frequencies only [ vector | {all} ]

%   OPTS.loadfft: load previously saved FFT blocks instead of recalculating [{false} | true]

%   OPTS.mean: provide a mean that is subtracted from each snapshot [ array of size X | 'blockwise' | {temporal mean of X; 0 if XFUN} ]

%   OPTS.nsave: number of most energtic modes to be saved [ integer | {all} ]

%   OPTS.isreal: complex-valuedity of X or represented by XFUN [{determined from X or first snapshot if XFUN is used} | logical ]

%   OPTS.nt: number of snapshots [ integer | {determined from X; defaults to 10000 if XFUN is used}]

%   OPTS.conflvl: confidence interval level [ scalar between 0 and 1 | {0.95} ]

%   OPTS.normvar: normalize each block by pointwise variance [{false} | true]

%

%   [L,PFUN,F] = SPOD(...,OPTS) returns a function PFUN instead of the SPOD

%   data matrix P if OPTS.savefft is true. The function returns the j-th

%   most energetic SPOD mode at the i-th frequency as p = PFUN(i,j) by

%   reading the modes from the saved files. Saving the data on the hard

% Determine whether data is real-valued or complex-valued to decide on one-

% or two-sided spectrum. If "opts.isreal" is not set, determine from data.

% If data is provided through a function handle XFUN and opts.isreal is not

% specified, deternime complex-valuedity from first snapshot.

if isfield(opts,'isreal')

    isrealx = opts.isreal;

elseif ~xfun

    isrealx = isreal(X);

else

    x1      = X(1);

    isrealx = isreal(x1);

    clear x1;

end

% get default spectral estimation parameters and options

[window,weight,nOvlp,dt,nDFT,nBlks,nTapers] = spod_parser(nt,nx,isrealx,varargin{:});

nSamples    = nBlks*nTapers;

% determine correction for FFT window gain

winWeight   = 1./mean(abs(window)); % row vector for multitaper                                          

% Use data mean if not provided through "opts.mean".

blk_mean    = false;

if isfield(opts,'mean')

    if strcmp('blockwise',opts.mean)

        blk_mean    = true;       

    end

end

if blk_mean

    mean_name   = 'blockwise mean';

elseif isfield(opts,'mean')

    x_mean      = opts.mean(:);

    mean_name   = 'user specified';

else

    switch xfun

        case true

            x_mean      = 0;

            warning('No mean subtracted. Consider providing long-time mean through "opts.mean" for better accuracy at low frequencies.');

            mean_name   = '0';

        case false

            x_mean      = mean(X,1);

            x_mean      = x_mean(:);

            mean_name   = 'data mean';

    end

end

disp(['Mean                      : ' mean_name]);

% obtain frequency axis

f = (0:nDFT-1)/dt/nDFT;

if isrealx

    f = (0:ceil(nDFT/2))/nDFT/dt;

else

    if mod(nDFT,2)==0

        f(nDFT/2+1:end) = f(nDFT/2+1:end)-1/dt;

    else

        f((nDFT+1)/2+1:end) = f((nDFT+1)/2+1:end)-1/dt;

    end

end

nFreq = length(f);

% set default for confidence interval 

if nargout>=4

    confint = true;

    if ~isfield(opts,'conflvl')

        opts.conflvl = 0.95;

    end

    xi2_upper   = 2*gammaincinv(1-opts.conflvl,nBlks);

    xi2_lower   = 2*gammaincinv(  opts.conflvl,nBlks);

    Lc          = zeros(nFreq,nBlks,2);

else

    confint = false;

    Lc      = [];

end

% set defaults for options for saving FFT data blocks

if ~isfield(opts,'savefreqs'),  opts.savefreqs  = 1:nFreq;   end

if opts.savefft

    if ~isfield(opts,'savedir'),    opts.savedir   = pwd;           end

    saveDir = fullfile(opts.savedir,['nfft' num2str(nDFT) '_novlp' num2str(nOvlp) '_nblks' num2str(nSamples)]);

    if ~exist(saveDir,'dir'),       mkdir(saveDir);                 end

    if ~isfield(opts,'nsave'),      opts.nsave      = nSamples;     end   

    if ~isfield(opts,'deletefft'),  opts.deletefft  = true;         end    

    omitFreqIdx = 1:nFreq; omitFreqIdx(opts.savefreqs) = []; 

end 

if ~isfield(opts,'loadfft'),    opts.loadfft    = false;     end

if ~isfield(opts,'normvar'),    opts.normvar    = false;     end

% loop over number of blocks and generate Fourier realizations

disp(' ')

disp('Calculating temporal DFT')

disp('------------------------------------')

if ~opts.savefft

    Q_hat = zeros(nFreq,nx,nSamples);

end

Q_blk       = zeros(nDFT,nx);

for iBlk    = 1:nBlks

    

    % check if all FFT files are pre-saved

    all_exist   = 0;

    if opts.loadfft        

        for iFreq = opts.savefreqs

            if ~isempty(dir(fullfile(saveDir,['fft_block' num2str([iBlk iFreq],'%.4i_freq%.4i.mat')])))

                all_exist   = all_exist + 1;

            end

        end

    end

    if opts.loadfft && all_exist==length(opts.savefreqs)

        disp(['loading FFT of block ' num2str(iBlk) '/' num2str(nBlks) ' from file'])

    else

        

        % get time index for present block

        offset                  = min((iBlk-1)*(nDFT-nOvlp)+nDFT,nt)-nDFT;

        timeIdx                 = (1:nDFT) + offset;

        % build present block

        if blk_mean, x_mean = 0; end

        if xfun

            for ti = timeIdx

                x                  = X(ti);

                Q_blk(ti-offset,:) = x(:) - x_mean;

            end

        else

            Q_blk   = bsxfun(@minus,X(timeIdx,:),x_mean.');

        end

        % if block mean is to be subtracted, do it now that all data is

        % collected

        if blk_mean

            Q_blk   = bsxfun(@minus,Q_blk,mean(Q_blk,1));           

        end        

        

        % normalize by pointwise variance

        if opts.normvar

            Q_var   = sum(bsxfun(@minus,Q_blk,mean(Q_blk,1)).^2,1)/(nDFT-1);

            % address division-by-0 problem with NaNs             

            Q_var(Q_var<4*eps)  = 1; 

            Q_blk   = bsxfun(@rdivide,Q_blk,Q_var);

        end        

        

        for iTaper  = 1:nTapers

            iSample = iBlk+((iTaper-1)*nBlks);

            if nTapers>1

               taperString  = [', taper ' num2str(iTaper) '/' num2str(nTapers)];

            else

               taperString  = []; 

            end

            disp(['block ' num2str(iBlk) '/' num2str(nBlks) taperString ' (snapshots ' ...

            num2str(timeIdx(1)) ':' num2str(timeIdx(end)) ')'])

            % window and Fourier transform block

            Q_blk_win               = bsxfun(@times,Q_blk,window(:,iTaper));

            Q_blk_hat               = winWeight(iTaper)/nDFT*fft(Q_blk_win);

            Q_blk_hat               = Q_blk_hat(1:nFreq,:);

            if ~opts.savefft

                % keep FFT blocks in memory

                Q_hat(:,:,iSample)         = Q_blk_hat;

            else

                for iFreq = opts.savefreqs

                    file = fullfile(saveDir,['fft_block' num2str([iSample iFreq],'%.4i_freq%.4i')]);

                    Q_blk_hat_fi        = single(Q_blk_hat(iFreq,:));

                    save(file,'Q_blk_hat_fi','-v7.3');

                end

            end

        end

    end

end

% loop over all frequencies and calculate SPOD

L   = zeros(nFreq,nSamples);

A   = zeros(nFreq,nSamples,nSamples);

disp(' ')

if nTapers>1

    disp('Calculating Multitaper SPOD')

else

    disp('Calculating SPOD')

end

disp('------------------------------------')

% unbiased estimator of CSD 

if blk_mean

    nIndep = nSamples-1;

else

    nIndep = nSamples;

end

if ~opts.savefft

    % keep everything in memory (default)

    P   = zeros(nFreq,nx,nSamples);

    for iFreq = 1:nFreq

        disp(['frequency ' num2str(iFreq) '/' num2str(nFreq) ' (f=' num2str(f(iFreq),'%.3g') ')'])

        Q_hat_f             = squeeze(Q_hat(iFreq,:,:));

        M                   = Q_hat_f'*bsxfun(@times,Q_hat_f,weight)/nIndep;

        [Theta,Lambda]      = eig(M);

        Lambda              = diag(Lambda);

        [Lambda,idx]        = sort(Lambda,'descend');

        Theta               = Theta(:,idx);

        Psi                 = Q_hat_f*Theta*diag(1./sqrt(Lambda)/sqrt(nIndep));

        P(iFreq,:,:)        = Psi;

        A(iFreq,:,:)        = diag(sqrt(nBlks)*sqrt(Lambda))*Theta';

        L(iFreq,:)          = abs(Lambda);

        % adjust mode energies for one-sided spectrum

        if isrealx

            if iFreq~=1&&iFreq~=nFreq

                L(iFreq,:)  = 2*L(iFreq,:);

            end

        end

        if confint

            Lc(iFreq,:,1)       = L(iFreq,:)*2*nIndep/xi2_lower;

            Lc(iFreq,:,2)       = L(iFreq,:)*2*nIndep/xi2_upper;

        end

    end

    P   = reshape(P,[nFreq dim(2:end) nSamples]);

else

    % save FFT blocks on hard drive (for large data)

    for iFreq = opts.savefreqs

        disp(['frequency ' num2str(iFreq) '/' num2str(nFreq) ' (f=' num2str(f(iFreq),'%.3g') ')'])

        % load FFT data from previously saved file

        Q_hat_f             = zeros(nx,nSamples);

        for iBlk    = 1:nSamples

            file    = fullfile(saveDir,['fft_block' num2str([iBlk iFreq],'%.4i_freq%.4i')]);

            load(file,'Q_blk_hat_fi');

            Q_hat_f(:,iBlk) = Q_blk_hat_fi;

        end

        M                   = Q_hat_f'*bsxfun(@times,Q_hat_f,weight)/nIndep;

        [Theta,Lambda]      = eig(M);

        Lambda              = diag(Lambda);

        [Lambda,idx]        = sort(Lambda,'descend');

        Theta               = Theta(:,idx);

        Psi                 = Q_hat_f*Theta*diag(1./sqrt(Lambda)/sqrt(nIndep));

        A(iFreq,:,:)        = diag(sqrt(nIndep)*sqrt(Lambda))*Theta';

        if opts.nsave>0

            Psi             = single(reshape(Psi(:,1:opts.nsave),[dim(2:end) opts.nsave]));

            file            = fullfile(saveDir,['spod_f' num2str(iFreq,'%.4i')]);

            save(file,'Psi','-v7.3');

        else

            Psi             = [];

        end

        L(iFreq,:)          = abs(Lambda);

        % adjust mode energies for one-sided spectrum

        if isrealx

            if iFreq~=1&&iFreq~=nFreq

                L(iFreq,:)  = 2*L(iFreq,:);

            end

        end

        if confint

            Lc(iFreq,:,1)       = L(iFreq,:)*2*nIndep/xi2_lower;

            Lc(iFreq,:,2)       = L(iFreq,:)*2*nIndep/xi2_upper;          

        end

    end

    % return anonymous function that loads SPOD modes from files instead of

    % actual solution

    P   = @(iFreq,iMode) getmode(iFreq,iMode,saveDir);

    

    file            = fullfile(saveDir,'spod_energy');

    save(file,'L','Lc','f','A','-v7.3');

    

    % clean up

    if opts.deletefft

        for iFreq = opts.savefreqs

            for iBlk    = 1:nSamples

                file    = fullfile(saveDir,['fft_block' num2str([iBlk iFreq],'%.4i_freq%.4i.mat')]);

                delete(file);

            end

        end

    end

    

    disp(' ')

    disp(['Results saved in folder ' saveDir])

end

end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [P] = getmode(iFreq,iMode,saveDir)

%GETMODE Anonymous function that loads SPOD modes from files

file        = matfile(fullfile(saveDir,['spod_f' num2str(iFreq,'%.4i')]));

dim         = size(file.Psi);

for di = 1:length(dim)-1

    idx{di} = 1:dim(di);

end

idx{di+1}   = iMode;

P           = file.Psi(idx{:});

end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [window,weight,nOvlp,dt,nDFT,nBlks,nTapers] = spod_parser(nt,nx,isrealx,varargin)

%SPOD_PARSER Parser for SPOD parameters

% read input arguments from cell array

window = []; weight = []; nOvlp = []; dt = [];

nvarargin = length(varargin);

if nvarargin >= 1

    window = varargin{1};

    if nvarargin >= 2

        weight   = varargin{2};

        if nvarargin >= 3

            nOvlp   = varargin{3};

            if nvarargin >= 4

                dt      = varargin{4};

            end

        end

    end

end

if size(window,2)>size(window,1) % ensure column matrix format 

    window = permute(window,[2 1]);

end

% check arguments and determine default spectral estimation parameters

% window size and type

if isempty(window)

    nDFT        = 2^floor(log2(nt/10));

    window      = hammwin(nDFT);

    window_name = 'Hamming';

elseif length(window)==1

    nDFT        = window;

    window      = hammwin(window);

    window_name = 'Hamming';

elseif length(window)==2

    nDFT        = window(1);

    bw          = window(2);

    nTapers     = floor(2*bw)-1;

    window      =  slepsec(nDFT,bw,nTapers);

    window_name = 'DPSS';    

elseif length(window) == 2^nextpow2(length(window))

    nDFT        = length(window);

    window_name = 'user specified';

else

    nDFT        = length(window);

    window_name = 'user specified';

end

nTapers     = size(window,2);

weight      = weight(:);

% block overlap

if isempty(nOvlp)

    nOvlp = floor(nDFT/2);

elseif nOvlp > nDFT-1

    error('Overlap too large.')

end

% time step between consecutive snapshots

if isempty(dt)

    dt = 1;

end

% inner product weight

if isempty(weight)

    weight      = ones(nx,1);

    weight_name = 'uniform';

elseif numel(weight) ~= nx

    error('Weights must have the same spatial dimensions as data.');

else

    weight_name = 'user specified';

end

% number of blocks

nBlks = floor((nt-nOvlp)/(nDFT-nOvlp));

% test feasibility

if nDFT < 4 || nBlks*nTapers < 3

    error('Spectral estimation parameters not meaningful.');

end

    

% display parameter summary

disp(' ')

if nTapers>1

    disp('Multitaper SPOD parameters')

else

    disp('SPOD parameters')

end

disp('------------------------------------')

if isrealx

    disp('Spectrum type             : one-sided (real-valued signal)')

else

    disp('Spectrum type             : two-sided (complex-valued signal)')

end

disp(['No. of snaphots per block : ' num2str(nDFT)])

disp(['Block overlap             : ' num2str(nOvlp)])

disp(['No. of blocks             : ' num2str(nBlks)])

disp(['Windowing fct. (time)     : ' window_name])

disp(['Weighting fct. (space)    : ' weight_name])

if nTapers>1

    disp(['No. of tapers             : ' num2str(nTapers)])

end

if exist('bw','var')

    disp(['Time-halfbandwidth product: ' num2str(bw)])

end

end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [window] = hammwin(N)

%HAMMWIN Standard Hamming window of lentgh N

    window = 0.54-0.46*cos(2*pi*(0:N-1)/(N-1))';

end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function [window] = slepsec(nDFT,bw,nTapers)

%SLEPSEC Discrete prolate spheroidal sequences of length nDFT and

%time-halfbandwidth product bw

    df      = bw/nDFT;

    j       = 1:nDFT-1;

    r1      = [df*2*pi, sin(2*pi*df*j)./j];

    S       = toeplitz(r1);

    [U,L]   = eig(S);

    [~,idx] = sort(diag(L),'descend');

    U       = U(:,idx);

    window  = U(:,1:nTapers);

end

⛄ 运行结果

⛄ 参考文献

 [1] A. Nekkanti, O. T. Schmidt, Frequency鈥搕ime analysis, low-rank reconstruction and denoising of turbulent flows using SPOD,  Journal of Fluid Mechanics 926, A26, 2021

⛄ Matlab代码关注

❤️部分理论引用网络文献,若有侵权联系博主删除

❤️ 关注我领取海量matlab电子书和数学建模资料

 


http://chatgpt.dhexx.cn/article/82xhgOLC.shtml

相关文章

通信基础 7 —— 遍历保密速率、谱分解物理意义

目录 遍历保密速率&#xff08;ergodic secrecy rate&#xff09;闭式解&#xff08;解析解&#xff09;和数值解闭式解数值解 拉普拉斯变换谱分解/正交分解 遍历保密速率&#xff08;ergodic secrecy rate&#xff09; 说遍历容量不十分准确&#xff0c;应该叫各态历经性容量…

【推荐系统】特征值分解(谱分解)和奇异值分解(SVD),即在PCA上的应用

特征值分解&#xff08;谱分解EVD&#xff09;和奇异值分解&#xff08;SVD&#xff09;&#xff0c;即在PCA上的应用 1. 概念 特征值分解和奇异值分解在机器学习领域都有着广泛的应用。两者有着很紧密的关系&#xff0c;二者的目的都是一样&#xff0c;就是提取出一个矩阵最…

R语言主成分分析PCA谱分解、奇异值分解预测分析运动员表现数据和降维可视化

最近我们被客户要求撰写关于主成分分析PCA的研究报告&#xff0c;包括一些图形和统计输出。 本文描述了如何 使用R执行主成分分析 ( PCA )。您将学习如何 使用 PCA预测 新的个体和变量坐标。我们还将提供 PCA 结果背后的理论。 主成分分析PCA降维方法和R语言分析葡萄酒可视化实…

【矩阵论】2. 矩阵分解——单阵谱分解

矩阵论 1. 准备知识——复数域上矩阵,Hermite变换) 1.准备知识——复数域上的内积域正交阵 1.准备知识——Hermite阵&#xff0c;二次型&#xff0c;矩阵合同&#xff0c;正定阵&#xff0c;幂0阵&#xff0c;幂等阵&#xff0c;矩阵的秩 2. 矩阵分解——SVD准备知识——奇异值…

可对角化和谱分解的区别

内容为个人理解&#xff0c;才疏学浅&#xff0c;如有错误&#xff0c;欢迎指正。 谱分解定理&#xff1a;向量空间V上的任意正规算子M&#xff0c;在V的某个标准正交基下可以对角化。反之&#xff0c;任意可对角化的算子都是正规的。 理解&#xff1a; &#xff08;1&#x…

R语言矩阵特征值分解(谱分解)和奇异值分解(SVD)特征向量分析有价证券数据

最近我们被客户要求撰写关于特征值分解的研究报告&#xff0c;包括一些图形和统计输出。 R语言是一门非常方便的数据分析语言&#xff0c;它内置了许多处理矩阵的方法。 作为数据分析的一部分&#xff0c;我们要在有价证券矩阵的操作上做一些工作&#xff0c;只需几行代码。 …

【矩阵论】2. 矩阵分解——正规谱分解

矩阵论 1. 准备知识——复数域上矩阵,Hermite变换) 1.准备知识——复数域上的内积域正交阵 1.准备知识——Hermite阵&#xff0c;二次型&#xff0c;矩阵合同&#xff0c;正定阵&#xff0c;幂0阵&#xff0c;幂等阵&#xff0c;矩阵的秩 2. 矩阵分解——SVD准备知识——奇异值…

【线性代数】矩阵的特征值分解(对角化、谱分解)

目录 1 前言2 矩阵的特征值分解2.1 从定义的角度理解2.2 从变换的角度理解(来自参考文献[3]) 3 对角矩阵&#xff08;补充&#xff09;3.1 对角矩阵的定义3.2 对角矩阵线性变换的几何意义 4 矩阵对角化5 相似矩阵与特征值6 参考文献 1 前言 矩阵的特征值分解又可以称作矩阵的对…

矩阵的谱分解 (详细推导步骤~~~特征值分解特征向量

所谓矩阵的分解&#xff0c;就是将一个矩阵写成结构比较简单的或性质比较熟悉的另一些矩阵的乘积。矩阵的分解方法有很多种&#xff0c;包括三角分解、QR&#xff08;正交三角&#xff09;分解、最大秩分解、奇异值分解和谱分解&#xff0c;所有这些分解在数值代数和最优化问题…

c语言-gotoxy实现先全部输出再做全部输入操作

需要用到的头文件&#xff1a; #include<windows.h> #include <iostream>代码&#xff1a; gotoxy(a,b)光标控制函数 a为行&#xff0c;b为列&#xff0c;坐标原点在左上角向右是行正方向&#xff0c;向下为列正方向 中文符号汉字在列方向为2个空间&#xff0c;英…

C语言 时钟模拟(gotoxy函数的运用)

时钟模拟&#xff0c;运用gotoxy()函数和Sleep()函数。 效果&#xff1a; #include <stdio.h> #include <windows.h> #include <time.h> #define XHOUR 40 //打印小时的起始x坐标&#xff0c;即a&#xff0c;g交点横坐标 #define YHOUR 27 #define HOUR 1 …

一些神奇的小函数(一)——gotoxy篇

一、gotoxy 1.作用&#xff08;1&#xff09;控制输出的位置① 样例 2.实现&#xff08;1&#xff09;c版 1.作用 &#xff08;1&#xff09;控制输出的位置 ① 样例 : 在代码中写上一句gotoxy(1,1)&#xff0c;然后cout<<“噢&#xff01;这个函数真有用&#xff01;…

Matlab sim函数的用法

一、引言 最近用Simulink做仿真的时候&#xff0c;需要从m文件里运行Simulink模型&#xff0c;而且需要在m文件中传递一些参数到Simulink模型&#xff0c;也需要将Simulink模型的运行结果发送回m文件&#xff0c;所以要用到sim函数。 查看了sim函数的help文档&#xff0c;并百…

CUDA10.0官方文档的翻译与学习之硬件实现

背景 在之前的文章中&#xff0c;我翻译了cuda10.0官方文档的前三章&#xff0c;这次就来翻译第四章——硬件实现 英伟达GPU架构通过由多线程的流式多处理器(SM)组成的可变数组编译&#xff0c;当一个主机CPU上的cuda程序调用了一个核网格&#xff0c;网格内的线程块将会被枚…

近距离看GPU计算(3)

在先前文章《近距离看GPU计算&#xff08;2&#xff09;》中&#xff0c;我们谈到现代GPU发展出SIMT(Single Instruction Multiple Thread)的执行结构&#xff0c;硬件线程池的线程们有相对独立的运行上下文&#xff0c;以Warp为单位分发到一组处理单元按SIMD的模式运行。这些W…

CPU线程与超线程技术

文章目录 一、CPU线程与OS线程1. CPU中的thread2. OS中的thread 二、HT/SMT技术1. 定义2. 原理3. 带来的问题 三、SIMT与SIMD1. SIMT2. SIMD3. 对比 一、CPU线程与OS线程 1. CPU中的thread CPU中的线程来自同步多线程&#xff08;SMT&#xff0c;Simultaneous Multi-threadin…

GPU 软硬件基本概念

术语: single instruction, multiple thread (SIMT)&#xff1a; a single instruction is executed on several function units in parallel GPU的硬件结构中与CUDA相关的几个概念&#xff1a;thread block grid warp sp sm streaming processor(sp): 最基本的处理单元&…

GPU异构计算基础知识

CUDA Toolkit Documentation (nvidia.com) host CPU和内存 (host memory)Device GPU和显存 (device memory) SIMT模型与SIMD模型的区别 SIMD(Single Instruction Multi Data&#xff0c;单指令多数据)模型要求同一个向量中的所有元素要在统一的同步组中一起执行&#xff0c;…

GPU硬件架构以及运行机制笔记

本文是对向往大神的文章的一个笔记。 想阅读原文章移步博客园搜索向往 原文章比较长&#xff0c;这是一个精简和自己的一些理解 这篇文章要带着下面的问题去看 1、GPU是如何与CPU协调工作的&#xff1f; 2、GPU也有缓存机制吗&#xff1f;有几层&#xff1f;它们的速度差异多…

4. CUDA编程手册中文版---硬件实现

第四章 硬件实现 更多精彩内容&#xff0c;请扫描下方二维码或者访问https://developer.nvidia.com/zh-cn/developer-program 来加入NVIDIA开发者计划 NVIDIA GPU 架构围绕可扩展的多线程流式多处理器 (SM: Streaming Multiprocessors) 阵列构建。当主机 CPU 上的 CUDA 程序调…