FPGA - DFT(离散傅里叶变换)—FFT(快速傅里叶变化)

一,DFT(离散傅里叶变换原理)

1,DFT(离散傅里叶变换原理)理论简介

        在数字信号处理中有一个基本概念:

        如果信号在频域离散的,则该信号在时域就表现为周期性的时间函数;相反,如果信号在时域离散的,则该信号在频域必然表现为周期性的频率函数。那么如果时域信号不仅是离散的,而且是周期的,那么由于它在时域离散,其频谱必是周期的;如果在时域是周期的,则相应的频谱必是离散的。换句话说,一个离散周期时间序列,它一定具有既是周期又是离散的频谱。还可以得出一个结论:一个域的离散就必然造成另一个域的周期延拓,这种离散变换,本质上都是周期的。

        一个连续信号经过理想采样后的表达式为:

其频谱函数Xa(jΩ)是上式的傅里叶变换,容易得出其傅里叶变换为: 

式中,Ω为模拟角频率,单位为rad/s,它与数字角频率ω之间的关系为ω=ΩT。对于数字信号来说,处理的信号其实是一个数字序列。因此,可用x(n)代替xa(nT),同时用X(ejω)代替xa(jω/T),则可以得到时域离散信号的频谱表达式,即: 

显然,X(ejω)是以2π为周期的函数。上式也印证了时域离散信号在频域表现为周期性函数的特性。 

        对于一个长度为N有限长序列,在频域表现为周期性的连续谱 X(ejω)。如果将有限长序列以N周期进行延拓,则在频域必将表现为周期性的离散谱X(ejωs),且单个周期的频谱形状有限长序列相同。因此,可以将X(ejωs)看成在频域对X(ejω)等间隔采样的结果。根据采样理论可知,要想采样后能够不失真地恢复原信号,采样速率必须满足一定的条件。假设时域信号的时间长度为NT,则在频域的一个周期内, 采样点数N0必须大于或等于N。

        用离散角频率变量kωs代替 中连续变量ωs,且取N0=N,则有限长序列的频谱表达式为:

        令以N为周期的函数 :

        x(n)为序列x(n)以N为周期的延拓,则上式可以写成: 

        将上式的两边同乘以,可以得到: 

        需要注意的是,上面2个式中的序列均是周期性的无限长序列。虽然是无限长序列,但只要知道该序列中一个周期的内容,序列的其他内容就知道了,所以这种无限长序列实际上只有N个序列值有信息,因此,周期序列与有限长序列有着本质的联系。 

        由于上面2个式中中只涉及0≤n≤N-1和0≤k≤N-1区间的值。也就是说,只涉及一个周期内的N个样本,因此,也可以用有限长序列x(n)和X(k),即各取一个周期来表示这些关系式。定义有限长序列x(n)和X(k)之间的关系为DFT,即:


2,DFT运算举例 

        例如,长度为4的有限长序列x1(n)=[1,1,1,1],其DFT运算过程如下:

        由于序列为全1,相当于对直流信号采样得到的数字信号,则仅存在零频分量(直流信号),不存在其他频率的信号,计算结果与实际情况相符。 

        例如,长度为4的有限长序列x2(n)=[1,2,3,4],其DFT运算过程如下:

        在MATLAB中的 fft()函数可以实现序列的频域变换。可在Matlab中使用“fft([1,1,1,1])”“fft([1,2,3,4])”可得到上面两个序列的DFT结果。 

3,DFT运算的常见问题

(1) 栅栏效应和序列补零

        利用DFT计算频谱,只能给出频谱在ωk=2πk/NΩk=2πk/NT的频率分量,即频谱的采样值,而不可能得到连续的频谱函数。就好像 通过栅栏看信号频谱一样,只能在离散点上得到信号频谱,这种现象称为栅栏效应

        在DFT计算过程中,如果序列长为N个点,则只要计算N点DFT。这意味着对序列x(n)的傅里叶变换在(0,2π)区间只计算N个点的值, 其频率采样间隔为2π/N 。 如 果 序 列 长 度 较 小 , 频 率 采 样 间 隔 ωs=2π/N可能太大,会导致不能直观地说明信号的频谱特性。有一种非常简单的方法能解决这一问题,即对序列的傅里叶变换以足够小的间隔进行采样,令数字频率间隔∆ωk=2π/L,L表示是DFT的点数。显然,要提高数字频率间隔,只需要增加L即可。当序列长度N较小时, 可采用在序列后面增加L-N个零值的办法对L点序列进行DFT以满足所需的频率采样间隔。这样可以在保持原来频谱形状不变的情况下, 使谱线加密,即增加频域采样点数,从而可以看到原来看不到的频谱分量。

(2)频谱泄漏和混叠失真

        对信号进行DFT计算,首先必须使其变成时间宽度有限的信号,方法是将序列x(n)与时间宽度有限的窗函数ω(n)相乘。例如,选用矩形窗来截断信号,在频域中相当于信号频谱与窗函数频谱的周期卷积卷积将造成频谱失真,且这种失真主要表现在原频谱的扩展,这种现象称为频谱泄漏。频谱泄漏会导致频谱扩展,会使信号的最高频率可 能超过采样频率的一半,从而造成混叠失真。频谱混叠 (Aliasing) 指的是在对模拟信号进行数字化采样时,由于采样频率不足,导致原本不同的频率成分在频谱中重叠在一起,造成频谱失真,难以区分不同频率成分的现象。

(3)频率分辨率与DFT参数的选择 


        在对信号进行DFT分析信号的频谱特征时,通常采用频率分辨率来表征在频率轴上所能得到的最小频率间隔。对于长度为N的DFT,其频率分辨率∆f=fs/N,其中fs为时域信号的采样频率,这里的数据长度N 必须是数据的有效长度。如果在x(n)中有两个频率分别为f1和f2的信 号,则在对x(n)用矩形窗截断时,要分辨这两个频率,必须满足下面的条件。

        DFT时的补零没有增加序列的有效长度,所以并不能提高分辨率; 但补零可以使数据N为2的整数幂次方。补零对原X(k)起到插值作用,一方面克服栅栏效应平滑谱的外观;另一方面,由于数据截断引起的频谱泄漏有可能在频谱中出现一些难以确认的谱峰,补零后有可能消除这种现象。 

二,FFT(快速傅里叶变换)

1、FFT(快速傅里叶变换)理论简介

        快速傅里叶变换(Fast Fourier Transform,FFT)并不是一种新的变换理论,而是离散傅里叶变换(Discrete Fourier Transform, DFT)的一种高效算法

        如何高效呢?简单看一下:

        在DFT的运算中。通常x(n)、X(k)和W_{N}^{n_{k}} 都是复数,因此 每计算一个X(k)值,必须要进行N次复数乘法和N-1次复数加法。而 X(k)共有N个值(0≤k≤N-1),所以要完成全部DFT的运算要进行N 2次 复数乘法和N(N-1)次复数加法。乘法运算比加法运算复杂,且运算时间更长,所占用的硬件资源也更多,因此可以用乘法运算量来衡量一个算法的运算量。由于复数乘法运算最终是通过实数乘 法运算来完成的,每个复数乘法运算需要4个实数乘法运算,因此完成 全部DFT运算需要进行4N^{2}次实数乘法运算。所以直接进行DFT运算的计算量太大,因此极大地限制了 DFT的应用。

        仔细观察DFT运算过程,会发现系数W_{N}^{n_{k}}具有对称性和周期 性,即

        利用系数W_{N}^{n_{k}}的周期性,在DFT运算中可以将某些项合并,从而减少DFT的运算量。又由于DFT的复数乘法运算次数与N2成正比,因此N越小越有利,可以利用对称性和周期性点数大的DFT分解成多个点数小的DFTFFT算法正是基于这样的基本思路发展起来的。 

        FFT算法可分为两大类:按时间抽取(Decimation-In-Time, DIT)按频率抽取(Decimation-In-Frequency,DIF)。为了提高运算速度,将DFT运算逐次分解成点数较小的DFT运算。如果FFT算法是通过逐次分解时间序列x(n)进行的,则这种算法称为按时间抽取FFT算 法;如果FFT算法是通过逐次分解频域序列X(k)进行的,则这种算法称为按频域抽取FFT算法

2,Xilinx  FFT IP核使用详解

Vivado中IP核的配置:

(1)创建工程

打开vivado,新建工程后从IP Catalog找到FFT并双击打开;

(2)第一页配置

        FFT核提供了4种运算结构,用户根据运算速度及硬件资源情况来选择。按运算速度从高到低(资源占用从多到少)的顺序排列,这4种运算结构分别是

  •         “Pipelined, Streaming I/O”
  •         “Radix-4, Burst I/O”
  •         “Radix-2, Burst I/O”
  •         “Radix-2 Lite, Burst I/O” 。

        “Pipelined, Streaming I/O” 可 对 连 续 输 入 数 据 进 行 FFT/IFFT;

        “Radix-4, Burst I/O”的数据输入和FFT/IFFT不能同时进行,也就是说,只能先输入数据,再进行FFT/IFFT,完成FFT/IFFT 后,再输入下一段数据,这种结构需要较长的时间来进行FFT/IFFT, 但只需要较少的硬件资源;

        “Radix-2, Burst I/O”与“Radix-4, Burst I/O”类似,由于蝶形运算单元较少,可以在牺牲运算速度的前 提下节约硬件资源;

        “Radix-2 Lite, Burst I/O”采用的蝶形运算单元比“Radix-2, Burst I/O”更少,可通过分时复用的方式进一步节 约硬件资源。 

(3)第二页配置

data format:下拉标签中,对应着FFT IP核支持两种数据类型: 

  1.  定点全精度 
  2.  定点缩减位宽 

scaling optios:缩放选项 :

  1.  block floating point :不管输入的格式如何,FFT变化内部都采用浮点,会根据每一级的的数据情况自动缩放。 这个模式的输入输出位宽一致,便于调用。
  2. scaled :在m_axis_data_tuser中会有5BIT表示每一级的缩放情况,在s_axis_config_data中会有相应的字段配置配置缩放因子.每一级别包含2个stage ,2个bit 表示一级缩放,一般0-3可选,如果log(NFFT)不是2的倍数,则最高一级的缩放只能在0-1之间选取。
  3. unscaled :不用担心变化过程中会出现溢出,但是输入是32bit的话,输出是64bit。

Aresten: 复位信号要勾选,至少保持两个时钟的低电平。

output odering options: 输出顺序选项。

  1.  nature order: FFT变化后的输出已经调整了顺序,按照xk_index自然顺序列出变化结果,
  2. bit/digital reserved oder就是按照变化后的顺序直接输出,是倒序输出,需要自己后续处理,
  3. cyclic perfix insertion :循环前缀插入,一般添加,在进行IFFT后可以根据s_axis_config_data中的CP长度配置自动添加CP。

optional output fileds :选项输出字段,

  1. xk_index:FFT 变幻的结果索引,在m_axis_data_user中有相应的字段。
  2.  OVFLO是变换中溢出的指示信号,对应event_fft_overflow.

(4)第三页配置

点击ok

(5)端口信号查看 

例化代码中真正对数据输入和FFT输出有关系的端口,只有s_axis_config_XXXs_axis_data_XXX,和m_axis_data_XXX,其中前2个是输入配置,第3个是输出配置。 

s_axis_config_tdata Input[N:0] 控制输入模式,进行fft/ifft以及衰减因子的设置,FWD_INV = 1做 fft,FWD_INV = 0做ifft。
s_axis_config_tvalidInput拉高两个时钟周期之后,将端口s_axis_data_tvalid和s_axis_data_tready拉高。
s_axis_config_treadyOutputs_axis_config_tvalid拉高两个时钟周期后,该口给1输出;若干个时钟周期后,自动归零。
s_axis_data_treadyOutputaresetn拉高两个时钟周期后,该口给1输出;此时ip核初始化完成,可进行数据输入。
s_axis_data_tvalidInput当s_axis_data_tready高电平后,将s_axis_data_tvalid拉高L个周期,输入L个数据进行fft;L是FFT的点数
s_axis_data_tdataInput[M:0]数据输入进行FFT运算。
s_axis_data_tlastInput输入L个数据后拉高,指示最后一个数据。
m_axis_data_tdataOutput[M1:0]高位为虚部,低位为实部。
m_axis_data_tvalidOutputfft结果输出时拉高。
m_axis_data_tuserOutput[M2:0]输出fft的地址值,输出值*fs/L为对应频点。
m_axis_data_treadyInput保持高电平,保证FFT单元处在计算模式,并且能够输出结算结果。
m_axis_data_tlastOutput当fft结果输出到最后一个结果时拉高,紧接着下一个时钟就拉低。

3,仿真测试

通过matlab对F(t) = 100 + 50cos(2pi10t) + 50cos(2pi30t) 这个信号以Fs = 100HZ进行采样,采样点数N = 256,采样完成后,将数据转换为16位二进制,并存入txt文件中。matlab程序如下:

clear

Fs=100;                         %采样率1ns一个点
N = 256;
n = 1:N;
t = n/Fs;
% 生成测试信号
f1 = 10;                   %
f2 = 30;                     %
s1 = cos(2*pi*f1*t);    
s2 = cos(2*pi*f2*t);
signalN = 2 + s1 + s2 ;
data_before_fft = 50*signalN;  %系数放大50倍


fp = fopen('G:\Xilinx_FPGA\matlab\data_before_fft.txt','w');
for i = 1:N
   if(data_before_fft(i)>=0)
       temp= dec2bin(data_before_fft(i),16);
   else
       temp= dec2bin(data_before_fft(i)+2^16+1, 16);
   end
    for j=1:16
        fprintf(fp,'%s',temp(j));
    end
    fprintf(fp,'\r\n');
end
fclose(fp);

y = fft(data_before_fft,N);
y = abs(y);
f = n*Fs/N;
plot(f,y);

得到采样数据,在vivado中新建测试文件:

TB文件如下:

// -----------------------------------------------------------------------------
// Author : LGR
// File   : TB_FFT.v
// Create : 2024-06-25 10:01:24
// Revise : 2024-06-25 10:17:30
// Editor : sublime text3, tab size (4)
// -----------------------------------------------------------------------------
`timescale 1ns / 1ps
module TB_FFT();

reg 				clk 							;
reg 				rst_n   						;
reg signed [15:0] 	Time_data_I[255:0]				;
reg 				data_finish_flag 				;
	
wire              	fft_s_config_tready 			;
	
reg signed [31:0] 	fft_s_data_tdata 				;
reg               	fft_s_data_tvalid				;
wire              	fft_s_data_tready				;
reg               	fft_s_data_tlast 				;
	
wire signed [63:0] 	fft_m_data_tdata				;
wire signed [7:0] 	fft_m_data_tuser				;
wire              	fft_m_data_tvalid				;
reg               	fft_m_data_tready				;
wire              	fft_m_data_tlast 				;
	
wire          		fft_event_frame_started			;
wire          		fft_event_tlast_unexpected		;
wire          		fft_event_tlast_missing			;
wire          		fft_event_status_channel_halt	;
wire          		fft_event_data_in_channel_halt	;
wire          		fft_event_data_out_channel_halt	;

reg [7:0]     		count							;

reg signed [25:0] 	fft_i_out 						; 
reg signed [25:0] 	fft_q_out 						;
reg signed [49:0] 	fft_abs 						;


initial begin
    clk = 1'b1;
    rst_n = 1'b0;
    fft_m_data_tready = 1'b1;
    $readmemb("G:/Xilinx_FPGA/matlab/data_before_fft.txt",Time_data_I);
end

always #5 clk = ~clk;

always @ (posedge clk or negedge rst_n) begin
    if(!rst_n) begin
        fft_s_data_tvalid <= 1'b0;
        fft_s_data_tdata  <= 32'd0;
        fft_s_data_tlast  <= 1'b0;
        data_finish_flag  <= 1'b0;
        count <= 8'd0;
        rst_n = 1'b1;
    end
    else if (fft_s_data_tready) begin 
        if(count == 8'd255) begin
            fft_s_data_tvalid <= 1'b1;
            fft_s_data_tlast  <= 1'b1;
            fft_s_data_tdata  <= {Time_data_I[count],16'd0};
            count <= 8'd0;
            data_finish_flag <= 1'b1;
        end
        else begin
            fft_s_data_tvalid <= 1'b1;
            fft_s_data_tlast  <= 1'b0;
            fft_s_data_tdata  <= {Time_data_I[count],16'd0};   
            count <= count + 1'b1;
        end
    end
    else begin
        fft_s_data_tvalid <= 1'b0;
        fft_s_data_tlast  <= 1'b0;
        fft_s_data_tdata <= fft_s_data_tdata;
        count <= count;
    end
end

always @ (posedge clk) begin
    if(fft_m_data_tvalid) begin
        fft_i_out <= fft_m_data_tdata[24:0];
        fft_q_out <= fft_m_data_tdata[56:32];
    end
end

always @ (posedge clk) begin
    fft_abs <= $signed(fft_i_out)* $signed(fft_i_out)+ $signed(fft_q_out)* $signed(fft_q_out);
end
//fft ip核例化
xfft_0 u_fft(
    .aclk(clk),                                                // 时钟信号(input)
    .aresetn(rst_n),                                           // 复位信号,低有效(input)
    .s_axis_config_tdata(8'd1),                                // ip核设置参数内容,为1时做FFT运算,为0时做IFFT运算(input)
    .s_axis_config_tvalid(1'b1),                               // ip核配置输入有效,可直接设置为1(input)
    .s_axis_config_tready(fft_s_config_tready),                // output wire s_axis_config_tready
    //作为接收时域数据时是从设备
    .s_axis_data_tdata(fft_s_data_tdata),                      // 把时域信号往FFT IP核传输的数据通道,[31:16]为虚部,[15:0]为实部(input,主->从)
    .s_axis_data_tvalid(fft_s_data_tvalid),                    // 表示主设备正在驱动一个有效的传输(input,主->从)
    .s_axis_data_tready(fft_s_data_tready),                    // 表示从设备已经准备好接收一次数据传输(output,从->主),当tvalid和tready同时为高时,启动数据传输
    .s_axis_data_tlast(fft_s_data_tlast),                      // 主设备向从设备发送传输结束信号(input,主->从,拉高为结束)
    //作为发送频谱数据时是主设备
    .m_axis_data_tdata(fft_m_data_tdata),                      // FFT输出的频谱数据,[47:24]对应的是虚部数据,[23:0]对应的是实部数据(output,主->从)。
    .m_axis_data_tuser(fft_m_data_tuser),                      // 输出频谱的索引(output,主->从),该值*fs/N即为对应频点;
    .m_axis_data_tvalid(fft_m_data_tvalid),                    // 表示主设备正在驱动一个有效的传输(output,主->从)
    .m_axis_data_tready(fft_m_data_tready),                    // 表示从设备已经准备好接收一次数据传输(input,从->主),当tvalid和tready同时为高时,启动数据传输
    .m_axis_data_tlast(fft_m_data_tlast),                      // 主设备向从设备发送传输结束信号(output,主->从,拉高为结束)
    //其他输出数据
    .event_frame_started(fft_event_frame_started),                // output wire event_frame_started
    .event_tlast_unexpected(fft_event_tlast_unexpected),          // output wire event_tlast_unexpected
    .event_tlast_missing(fft_event_tlast_missing),                // output wire event_tlast_missing
    .event_status_channel_halt(fft_event_status_channel_halt),    // output wire event_status_channel_halt
    .event_data_in_channel_halt(fft_event_data_in_channel_halt),  // output wire event_data_in_channel_halt
    .event_data_out_channel_halt(fft_event_data_out_channel_halt) // output wire event_data_out_channel_halt
  );
    

endmodule

首先fft_s_data_tready 拉高,表示IP核准备好接受数据,然后在下一个时钟将fft_s_data_tvaild拉高。准备向IP核写入数据,count开始计数。

在 fft_s_data_tvaild有效期间,读出txt文件的数据,按顺序写入到fft_s_data_tdata中,当count计数到255,即最后一个数据时,将fft_s_data_tlast信号拉高,代表数据写入完成。

fft_m_data_tvalid变为高电平,代表fft_m_data_tdata中将输出有效数据,即256点FFT的计算结果。

IP核的计算结果与matlab的计算结果相对比,发现数据略有偏差。

三,总结

以上从原理介绍了DFT(离散傅里叶变换原理),然后再介绍了FFT(快速傅里叶变换)以及IP核的使用,和IP核使用参数以及配置。


参考文献:

[1]朱永前,李霄.在FPGA上实现FFT的高效串行流水线结构[J].火控雷达技术,2023,52(02):61-65.DOI:10.19472/j.cnki.1008-8652.2023.02.010.

[2]侯晓晨,孟骁,陈昊.基于FPGA的混合基FFT算法设计与实现[J].太赫兹科学与电子信息学报,2021,19(02):303-307.

[3]杜勇.Xilinx FPGA 数字信号处理设计[M].电子工业出版社:202003.339. 

[4]https://blog.csdn.net/weixin_41594632/article/details/112689545

[5]尹艳清,杨湘杰,李必超,等.基于FPGA的快速傅立叶变换算法的实现[J].电子技术与软件工程,2021,(06):84-85.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/742216.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何确保消息不被重复消费

一、重复消费问题出现的原因 导致重复消费的原因可能出现在生产者&#xff0c;也可能出现在 MQ 或 消费者。这里说的重复消费问题是指同一个数据被执行了两次&#xff0c;不单单指 MQ 中一条消息被消费了两次&#xff0c;也可能是 MQ 中存在两条一模一样的消费。 生产者&…

LabVIEW高精度电能质量监测系统

LabVIEW和研华采集卡的高精度电能质量监测系统利用虚拟仪器技术&#xff0c;实时监测电能质量的关键指标&#xff0c;如三相电压、频率和谐波。通过提高监测精度和效率&#xff0c;改善电网的电能质量。系 一、系统背景 电能作为现代社会的关键能源&#xff0c;其质量直接影响…

【工具测评】ONLYOFFICE——你的下一款桌面编辑器

文章目录 前言一、安装1.1 跳转官网下载安装包1.2 安装步骤 二、功能介绍2.1 功能全面的 PDF 编辑器2.2 PDF 表单2.3 文本文档编辑器的更新2.4 电子表格编辑器的更新2.5 演示文稿编辑器有哪些更新2.6 所有编辑器中的改进内容2.7 从右至左显示 & 新的本地化选项2.8 可用性提…

Yolo v5实现细节

Yolo v5实现细节 SiLU激活函数 swish和SiLU激活函数:其中β是常量或者是可学习的参数 首先引入swish函数的表达形式&#xff1a; f ( x ) x ⋅ sigmoid ⁡ ( β x ) f(x)x \cdot \operatorname{sigmoid}(\beta x) f(x)x⋅sigmoid(βx) 如果β 1即SiLU激活函数: f ( x ) x …

基于STM32的智能环境监测系统

目录 引言环境准备智能环境监测系统基础代码实现&#xff1a;实现智能环境监测系统 4.1 数据采集模块4.2 数据处理与分析4.3 通信模块实现4.4 用户界面与数据可视化应用场景&#xff1a;环境监测与管理问题解决方案与优化收尾与总结 1. 引言 智能环境监测系统通过使用STM32嵌…

Navicat连接Oracle出现Oracle library is not loaded的解决方法

目录 1. 问题所示2. 原理分析3. 解决方法1. 问题所示 使用Navicat链接Oracle的时候,出现如下提示:Oracle library is not loaded. 截图如下所示: 2. 原理分析 通常是由于缺少必需的 Oracle 客户端库或环境变量未正确配置所致 还有一种情况是 32位与64位的不匹配:Navica…

如何挑选护眼灯?一分钟带你了解挑选护眼灯的六大准则!

小时候&#xff0c;对正确用眼知识一无所知&#xff0c;也不明白何种光线环境对眼睛最为友善&#xff0c;结果如今的近视度数已濒临千度大关。虽然早已习惯佩戴眼镜的生活&#xff0c;但近视所带来的诸多不便仍旧在日常生活中无处不在。因此&#xff0c;对于家中孩子的视力健康…

昇思25天学习打卡Day01

实验结果 心得体会 趁着假期&#xff0c;跟谁官方实战营开始系统学习MindSpore深度学习框架。昇思MindSpore是一个全场景深度学习框架&#xff0c;旨在实现易开发、高效执行、全场景统一部署三大目标。其中易开发表现为API友好&#xff0c;调试难度低&#xff1b;高效执行包括…

探索认知智能的未来:知识图谱的崛起

知识图谱点燃语言模型的潜能 ©作者| 潇潇 来源|神州问学 一、 人工智能的三个层次 在人工智能的发展历程中&#xff0c;我们见证了从简单计算到复杂认知的飞跃。人工智能的发展可以概括为三个主要层次&#xff1a;计算智能、感知智能和认知智能。这三个层次不仅代表了技…

Python学习笔记19:进阶篇(八)常见标准库使用之glob模块和argparse模块

前言 本文是根据python官方教程中标准库模块的介绍&#xff0c;自己查询资料并整理&#xff0c;编写代码示例做出的学习笔记。 根据模块知识&#xff0c;一次讲解单个或者多个模块的内容。 这里贴一下教程地址&#xff1a;https://docs.python.org/zh-cn/3/tutorial/stdlib.h…

执行shell脚本出现 $‘ \r‘ 符号导致执行失败【解决】

&#x1f468;‍&#x1f393;博主简介 &#x1f3c5;CSDN博客专家   &#x1f3c5;云计算领域优质创作者   &#x1f3c5;华为云开发者社区专家博主   &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社区&#xff1a;运维交流社区 欢迎大家的加入&#xff01…

stm32单片机程序烧写方式ISP和IAP区别

在线编程目前有两种实现方法&#xff1a;在系统编程&#xff08;ISP&#xff09;和在应用编程&#xff08;IAP&#xff09;。 ISP一般是通过单片机专用的串行编程接口对单片机内部的Flash存储器进行编程&#xff0c;而IAP技术是从结构上将Flash存储器映射为两个存储体&#xf…

Trilium Notes浏览器插件保存网页内容到docker私有化部署

利用Trilium浏览器插件可以很方便的把网页内容保存到Trilium&#xff0c;需要先在docker部署好trilium&#xff0c;还没有部署的可以先看这篇文章&#xff1a;trilium笔记私有化部署-www.88531.cn资享网 1.下载Trilium浏览器插件&#xff1a;https://www.npspro.cn/33462.html…

PyTorch 2.2重大升级:引入FlashAttention-2,性能暴增2倍!

【新智元导读】新的一年&#xff0c;PyTorch也迎来了重大更新&#xff0c;PyTorch 2.2集成了FlashAttention-2和AOTInductor等新特性&#xff0c;计算性能翻倍。 新的一年&#xff0c;PyTorch也迎来了重大更新&#xff01; 继去年十月份的PyTorch大会发布了2.1版本之后&#…

Python笔记 文件的写,追加,备份操作

一、文件的写操作 案例演示&#xff1a; # 1.打开文件 f open(python.txt,w)# 2.文件写入 f.write(hello world)# 3.内容刷新 f.flush() 注意&#xff1a; 直接调用write&#xff0c;内容并为真正的写入文件&#xff0c;二十会积攒在程序的内存中&#xff0c;称之为缓冲区…

【Matlab】CNN-LSTM分类 卷积神经网络-长短期记忆神经网络组合模型(附代码)

资源下载&#xff1a; https://download.csdn.net/download/vvoennvv/89466499 分类算法资源合集&#xff1a;https://download.csdn.net/download/vvoennvv/89466519 目录 Matlab SVM支持向量机分类算法 Matlab RF随机森林分类算法 Matlab RBF径向基神经网络分类算法 Ma…

轻松掌握App推广命脉!Xinstall渠道效果统计功能,你的营销利器

在移动互联网时代&#xff0c;App的推广与运营成为了每个开发者、运营者必须面对的重要课题。然而&#xff0c;如何精准地掌握App的推广效果&#xff0c;优化渠道投放&#xff0c;成为了众多推广者心中的痛点和难题。今天&#xff0c;我们将为大家介绍一款能够轻松解决这一问题…

象战----第十二届中山市邀请赛正赛

本次的题解一定让大家享受脑细胞碰撞与再生死亡的感受&#xff01;定然酣畅淋漓&#xff01;请耐心的读完 简称&#xff1a;让脑袋死机。。。 象战 老规矩先分析在打码&#xff1a; 注意到题目告诉我们&#xff1a;四个角落是不能放的 那么 我们设象在(i,j).(注意&#xff1a…

ONLYOFFICE 8.1版本桌面编辑器测评:重塑办公效率的巅峰之作

在数字化办公日益普及的今天&#xff0c;一款高效、便捷且功能强大的桌面编辑器成为了职场人士不可或缺的工具。ONLYOFFICE 8.1版本桌面编辑器凭借其卓越的性能和丰富的功能&#xff0c;成功吸引了众多用户的目光。今天&#xff0c;我们将对ONLYOFFICE 8.1版本桌面编辑器进行全…

Spring Boot整合Druid:轻松实现SQL监控和数据库密码加密

文章目录 1 引言1.1 简介1.2 Druid的功能1.3 竞品对比 2 准备工作2.1 项目环境 3 集成Druid3.1 添加依赖3.2 配置Druid3.3 编写测试类测试3.4 访问控制台3.5 测试SQL监控3.6 数据库密码加密3.6.1 执行命令加密数据库密码3.6.2 配置参数3.6.3 测试 4 总结 1 引言 1.1 简介 Dru…