寄存器使用过多成为CUDA程序瓶颈的情况分析

原文地址: http://blog.sina.com.cn/s/blog_c25b76e20101jywj.html 作者:英伟达高性能计算
事实上,寄存器数量限制程序性能的案例还是比较少的。
首先您要明确是否真的是此因素导致了您程序性能无法进一步提升。

寄存器影响主要两个方面:active warp 的数量(即occupancy )和寄存器溢出导致的local memory的传输。

首先看active warp:

什么时候是因为寄存器使用过多导致active warp数量少,导致性能低呢?

第一,程序为延迟密集型程序,也就是说程序大部分时间是在等待高延迟指令返回结果(其他两种为指令密集型和内存密集型,详见GTC 录像中讲座Analysis Driven Optimization with CUDA http://www.gputechconf.com/gtcnew/on-demand-gtc.php )。因为只有在这种情况下程序才需要更多的active warp来隐藏延迟。

第二,仅仅通过instruction by byte ratio, instruction throughput, memory throughput来确定是否为延迟密集型是不完整的。很多情况下,当我们的程序有较严重的负载不均衡的现象,即某几个block或某些warps运行时间远超过其他时,或者没有分配足够的blocks和threads时。instruction throughput 和 memory throughput 也会很低。这两种情况的特征是实际的occupancy数量远远低于理论的occupancy。实际occupancy可以通过以下公式求出:
actual occupancy = active warps/duration/#sm/frequency_of_gpu/max_active_warps_in_a_sm
其中active warps 可以通过Toolkit 中提供的profiler:nvvp 测得。duration 为kernel运行时间,#sm为此gpu中sm的数量,frequency_of_gpu为gpu的主频,max_active_warps_in_a_sm为一个sm最大可以有多少个resident warps。理论occupance同样可以通过nvvp测得,或者通过toolkit中提供的excel工具测得。

第三,即使理论和实际occupancy接近,也不一定是由于寄存器使用过多导致occupancy少,occupancy还受到shared memory,每个block分配多少线程的影响,可以通过excel工具查看。

只有在程序为延迟密集型程序,且经验证,理论occupancy和实际occupancy接近时,并通过excel工具查得确实寄存器为限制因素时才可得出寄存器使用过多导致性能无法进一步提高的结论。

另外,再来看寄存器溢出导致local memory传输制约程序性能的可能性:
如果是内存传输为程序瓶颈,那么kernel一定是内存密集型。其表现为程序sm到L2内存传输速度基本达到gpu峰值。至于判断是寄存器溢出导致的local memory,还是局部数组存储导致的local memory成为瓶颈还是由于一般的global memory的访问或者tex访问。我们可以通过查看Profiler 中的Metrics: Local Memory Overhead查看,看是否local memory的吞吐量占其中主要部分。在local memory的吞吐占主要部分,且代码中用数组存储局部变量的情况时,才可得出寄存器溢出导致local memory传输制约程序性能的结论。

如果寄存器使用确实成为程序瓶颈。以下策略可以减少程序中寄存器的使用。
1、 拆分代码为较小的Kernel(一般需要同时修改算法才能达到比较好的效果)。
2、 运用maxrregcount编译选项控制寄存器使用。
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用VB程序通过RS485通信线读写西门子PLC的寄存器,需要注意以下几点: 1. 确认RS485通信线的连接方式:通常情况下,RS485通信线需要连接到PLC的通信模块上,然后通过编程控制通信模块与PLC之间的通信。 2. 使用合适的RS485通信库:在VB程序使用RS485通信需要借助第三方库或API,例如使用WinAPI函数`CreateFile`、`WriteFile`、`ReadFile`等来实现串口通信。也可以使用一些第三方的串口通信库,例如MSComm控件、SerialPort类等。 3. 确认PLC的通信协议:不同的PLC系统使用的通信协议不同,需要根据具体的PLC系统来选择合适的通信协议。 下面是一个简单的示例代码,演示了如何使用VB程序通过RS485通信线读写西门子PLC的寄存器: ```vb ' 创建一个SerialPort对象 Dim sp As New System.IO.Ports.SerialPort ' 配置串口参数 sp.PortName = "COM1" sp.BaudRate = 9600 sp.Parity = IO.Ports.Parity.None sp.DataBits = 8 sp.StopBits = IO.Ports.StopBits.One ' 打开串口 sp.Open() ' 发送读取寄存器的命令 Dim cmd() As Byte = {&H3, &H0, &H1, &H0, &H2, &H41, &H30} sp.Write(cmd, 0, cmd.Length) ' 等待PLC响应 Threading.Thread.Sleep(100) ' 读取PLC返回的数据 Dim nBytesToRead As Integer = sp.BytesToRead Dim buffer(nBytesToRead - 1) As Byte sp.Read(buffer, 0, nBytesToRead) ' 解析数据 Dim nValue As Integer = (buffer(3) << 8) + buffer(4) ' 修改寄存器的值 nValue = nValue + 1 Dim cmd2() As Byte = {&H10, &H0, &H1, &H0, &H2, &H4, &H8, &H0, &H1, &H0, &H0, &H0} cmd2(9) = nValue And &HFF cmd2(10) = nValue >> 8 sp.Write(cmd2, 0, cmd2.Length) ' 关闭串口 sp.Close() ``` 在上述代码,首先创建了一个SerialPort对象,并配置了串口参数。然后通过向串口发送读取寄存器的命令,读取了DB1寄存器的值,并解析了返回的数据。接着,修改了寄存器的值,并通过向串口发送写入寄存器的命令,将修改后的值写入到PLC。最后,关闭了串口。 需要注意的是,发送读取和写入寄存器的命令需要根据PLC的通信协议来确定。在上述代码,发送读取寄存器的命令使用了Modbus RTU协议的格式,发送写入寄存器的命令使用了S7协议的格式。同时,读取和写入数据时需要注意字节序的问题,因为不同的PLC系统可能使用不同的字节序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值