cs231n_深度学习软硬件

文章讨论了GPU和TPU在硬件加速深度学习中的差异,强调了GPU的并行处理能力和专门的tensorcore。在软件方面,重点介绍了PyTorch的自动梯度计算、Module模块化设计以及动态图和静态图的概念。PyTorch的自动Grad功能简化了反向传播过程,而nn.Module和dataloader等功能则方便了网络构建和数据处理。此外,文章还提到了Tensorboard在训练过程中的可视化作用。
部署运行你感兴趣的模型镜像

1. 硬件

Nvidia GPU

Goolgle TPU

1. GPU,核心数量很多,单核相对较慢。CPU,核心数量少,单核很快很强。

2. GPU中有针对deep learning特殊设计的tensor core,可以进行大量的并行的矩阵运算

3. GPU的内存和带宽都影响训练的速度

 

 

2. 软件

当年很多的框架,

 

3. Pytorch

网络结构,梯度计算,反向传播

Tensor, 类似于Numpy array,可以在gpu上进行运算的矩阵。

完全手动实现所有的,梯度计算,loss计算,梯度反向传播,权重更新。

 

AutoGrad,可以建立计算图,并自动的计算梯度,可以用于反向传播。

        requires_grad=True  # 选择这个flag,涉及到这个变量的计算就会自动计算梯度

        with torch.no_grad(): # 一般用在反向梯度传播,不需要计算梯度

                backprop

                xxx.grad.zero_() # 要清零

        可以自定义函数,并自定义梯度的计算,这样pytorch在使用这个函数的时候,整个函数就变成一个单独的节点,而不是拆散变为基本的计算单元。

 

Module,可以模块化设计的网络结构,可以保存weight和状态。

        torch.nn,定义网络结构,定义loss,定义optimizer,high level的api,大部分常用的网络结构都可以这么操作。

利用了nn.Sequential(),nn.functional.mse_loss(),手写梯度更新

 

利用了nn.Sequential(), nn.functional.mse_loss(),torch.optim.Adam():调用adam optimizer,不用手动更新

继承nn.module,

        __init__定义网络结构,

        forward(),定义前向传播,

训练迭代:前向传播,计算loss,loss梯度计算,调用optimizer,更新weights,循环。

定义一些block,然后直接用block建立完整的网络

 

 

数据输入,

dataloader

静态图,动态图,

1. pytorch 默认是动态图,每一次前向传播,建立动态图,反向传播之后,扔掉计算图并重新建立。更灵活,更适合尝试一些idea,但是计算资源会被浪费。

2. 可以支持静态图,jit, just in time

graph = torch.jit.script(model),动态图转化为静态图

或者通过修饰器的方法来实现。

3. 静态图更适合C++部署

4. 动态图方便调试

Tensorboard,

loss, learning rate等训练过程数据的logging和可视化

您可能感兴趣的与本文相关的镜像

PyTorch 2.5

PyTorch 2.5

PyTorch
Cuda

PyTorch 是一个开源的 Python 机器学习库,基于 Torch 库,底层由 C++ 实现,应用于人工智能领域,如计算机视觉和自然语言处理

module spi ( output reg [31:0] receive_data0, output reg [31:0] receive_data1, output reg [31:0] receive_data2, output reg [31:0] receive_data3, output reg [31:0] receive_data4, // output reg [31:0] receive_data5, // output reg [31:0] receive_data6, // output reg [31:0] receive_data7, input [31:0] sending_data0, input [31:0] sending_data1, input [31:0] sending_data2, input [31:0] sending_data3, input [31:0] sending_data4, // input [31:0] sending_data5, // input [31:0] sending_data6, // input [31:0] sending_data7, input clk , input rst_n , input CS_N , input SCK , input MOSI , output reg MISO , output reg mark ,//单个数据传输完成标志 output reg end_mark //整体传输完成标志 ); //SPI数据发送宽度和深度的定义 //根据实际收发数据的宽度和深度定义width和depth parameter width= 'd32;//数据传输宽度 parameter depth= 'd5;//数据传输深度 parameter total_width = width*depth-'d1;//数据传输总宽度 reg [total_width:0] txd_data;//总发送位宽=width*depth-1; reg [total_width:0] rxd_data;//总接收位宽=width*depth-1; //数据按位拼接寄存器 //根据实际收发数据的深度注释或开启对应的项 always@(posedge clk or negedge rst_n)begin if(!rst_n) txd_data <= 'd0; else begin txd_data[width-1:0] <= sending_data0; txd_data[width*'d2-1:width*'d1] <= sending_data1; txd_data[width*'d3-1:width*'d2] <= sending_data2; txd_data[width*'d4-1:width*'d3] <= sending_data3; txd_data[width*'d5-1:width*'d4] <= sending_data4; // txd_data[width*'d6-1:width*'d5] <= sending_data5; // txd_data[width*'d7-1:width*'d6] <= sending_data6; // txd_data[width*'d8-1:width*'d7] <= sending_data7; receive_data0 <= rxd_data[width-1:0] ; receive_data1 <= rxd_data[width*'d2-1:width*'d1]; receive_data2 <= rxd_data[width*'d3-1:width*'d2]; receive_data3 <= rxd_data[width*'d4-1:width*'d3]; receive_data4 <= rxd_data[width*'d5-1:width*'d4]; // receive_data5 <= rxd_data[width*'d6-1:width*'d5]; // receive_data6 <= rxd_data[width*'d7-1:width*'d6]; // receive_data7 <= rxd_data[width*'d8-1:width*'d7]; end end //************************片选控制信号数据输入及消抖******************** reg CS_N1,CS_N2; wire CS_N_n; always@(posedge clk or negedge rst_n)begin if(!rst_n)begin CS_N1 <= 'd0; CS_N2 <= 'd0; end else begin CS_N1 <= CS_N; CS_N2 <= CS_N1; end end assign CS_N_n = (CS_N1 & ~CS_N2)? 1'b1:1'b0; //捕捉下降沿 assign CS_N_p = (~CS_N1 & CS_N2)? 1'b1:1'b0; //捕捉上升沿 //--------------捕获 sck-------------- reg sck_r0,sck_r1,sck_r2;//打三拍 wire sck_n,sck_p; always@(posedge clk or negedge rst_n)begin if(!rst_n)begin sck_r0 <= 1'b0; sck_r1 <= 1'b0; sck_r2 <= 1'b0; end else if(CS_N2)begin sck_r0 <= 1'b0; sck_r1 <= 1'b0; sck_r2 <= 1'b0; end else begin sck_r0 <= SCK; sck_r1 <= sck_r0; sck_r2 <= sck_r1; end end assign sck_n = (sck_r1 & ~sck_r2)? 1'b1:1'b0; //捕捉下降沿 // assign sck_p = (~sck_r1 & sck_r2)? 1'b1:1'b0; //捕捉上升沿 //spi数据循环收发 //接收和发送同时进行,依赖同一触发源,下降沿后三个时钟周期,确保介于下降沿于上升沿之间 reg [31:0] width_cnt ;//移位计数器 always@(posedge clk or negedge rst_n)begin if(!rst_n)begin rxd_data <='d0; width_cnt <= total_width; end // else if(CS_N_n)begin // width_cnt <= total_width; // end else if(sck_n)begin//下降沿打三拍发送数据同时对方已经发送完成,FPGA已经可以接收数据了 MISO <= txd_data[width_cnt]; rxd_data[width_cnt] <= MOSI; if(width_cnt) width_cnt <= width_cnt-'d1; else width_cnt <= total_width; end end //spi数据接收结束标志信号 //mark为单个数据传输完成标志位 //end_mark为整体数据发送完成标志位 reg [31:0] width_cnt_r; always@(posedge clk or negedge rst_n)begin if(!rst_n) width_cnt_r <= 1'd0; else width_cnt_r <= width_cnt; end always@(posedge clk or negedge rst_n)begin if(!rst_n) mark <= 1'd0; else if(width_cnt_r!=width_cnt&&(width_cnt+'d1)%width=='d0) mark <= 'd1; else mark <= 'd0; end always@(posedge clk or negedge rst_n)begin if(!rst_n) end_mark <= 1'd0; else if((width_cnt_r!=width_cnt)&&(width_cnt)==total_width) end_mark <= 'd1; else end_mark <= 'd0; end endmodule找出里面的问题
09-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值