stream set blockingg是异步的配置吗

network(1)
文章写得很详细很清楚了,对我的理解帮助很大。
转载自:。
概括来说,一个IO操作可以分为两个部分:发出请求、结果完成。如果从发出请求到结果返回,一直Block,那就是Blocking IO;如果发出请求就可以返回(结果完成不考虑),就是non-blocking IO;如果发出请求就返回,结果返回是Block在select或者poll上的,则其只能称为IO multiplexing;如果发出请求就返回,结果返回通过Call Back的方式被处理,就是AIO。
文[2]中图画的不错,说的也比较清楚借来用一下。
Blocking IO
这个最好理解了,在Blocking IO模式下,函数调用只有在操作完成后才会返回。下图是它调用过程的图示:
重点解释下上图,下面例子都会讲到。首先application调用 recvfrom()转入kernel,注意kernel有2个过程,wait for data和copy data from kernel to user。直到最后copy complete后,recvfrom()才返回。此过程一直是阻塞的。
Non-Blocking IO
Non-Blocking 是Blocking的反,也就是说,即使操作没有完成,函数也可以返回。调用过程如下:
可以看见,如果直接操作它,那就是个轮询。。直到内核缓冲区有数据
AIO也是这样啊?对!这是Non-Blocking IO 和AIO的共同点。其实从概念层面来说Non-Blocking IO 就是AIO,他们没有什么区别。但是Non-Blocking IO是对文件描述符(*nix)或者Handle(Windows)的设置,在执行操作时不需要特殊的数据结构。Non-Blocking IO提交请求后只能通过提交的操作函数来查询操作是否完成,这是一个很大的限制。而AIO往往会提供多种通知或者查询机制,也就是说用Non-Blocking IO时只能轮询,而AIO有更多选择。所以是否支持轮询外的其他机制是AIO和Non-Blocking IO的区别。
Non-Blocking IO和Blocking IO的区别仅仅在操作是否能够立刻完成,如果能够立刻完成,IO函数的行为是一样的;如果不能立刻完成,Non-Blocking IO会返回EAGAIN或者EWOULDBLOCK,而Blocking IO会一直阻塞。
I/O multiplexing (select and poll)
最常见的I/O复用模型,select。
select先阻塞,有活动套接字才返回。与blocking I/O相比,select会有两次系统调用,但是select能处理多个套接字。
signal driven I/O (SIGIO)
只有UNIX系统支持,感兴趣的课查阅相关资料
与I/O multiplexing (select and poll)相比,它的优势是,免去了select的阻塞与轮询,当有活跃套接字时,由注册的handler处理。
Asynchronous I/O (the POSIX aio_functions)
很少有*nix系统支持,windows的IOCP则是此模型。
The POSIX asynchronous I/O (AIO) interface allows applications to initiate one or more I/O operations that are performed asynchronously (i.e., in the background). The application can elect to be notified of completion of the I/O operation in a variety of ways: by delivery of a signal, by instantiation of a thread, or no notification at all.
AIO让应用发起一个操作请求,让这个请求被异步地执行。应用可以选择在操作完成时被通知到或者不被通知。所以通知机制并不是AIO的核心,但是需要提供几种选择。在Windows上,Overlapped IO是AIO的实现,IOCP在Overlapped IO的基础上提供了高效的通知机制。
完全异步的I/O复用机制,因为纵观上面其它四种模型,至少都会在由kernel copy data to application时阻塞。而该模型是当copy完成后才通知application,可见是纯异步的。好像只有windows的完成端口是这个模型,效率也很出色。
下面是以上五种模型的比较
可以看出,越往后,阻塞越少,理论上效率也是最优。
下面可以把select,epoll,iocp,kqueue按号入座。
select和iocp分别对应第3种与第5种模型,那么epoll与kqueue呢?其实也于select属于同一种模型,只是更高级一些,可以看作有了第4种模型的某些特性,如callback机制。
那么,为什么epoll,kqueue比select高级?
答案是,他们无轮询。因为他们用callback取代了。想想看,当套接字比较多的时候,每次select()都要通过遍历FD_SETSIZE个Socket来完成调度,不管哪个Socket是活跃的,都遍历一遍。这会浪费很多CPU时间。如果能给套接字注册某个回调函数,当他们活跃时,自动完成相关操作,那就避免了轮询,这正是epoll与kqueue做的。
windows or *nix (IOCP or kqueue/epoll)?
诚然,Windows的IOCP非常出色,目前很少有支持asynchronous I/O的系统,但是由于其系统本身的局限性,大型服务器还是在UNIX下。而且正如上面所述,kqueue/epoll 与 IOCP相比,就是多了一层从内核copy数据到应用层的阻塞,从而不能算作asynchronous I/O类。但是,这层小小的阻塞无足轻重,kqueue与epoll已经做得很优秀了。
提供一致的接口,IO Design Patterns
实际上,不管是哪种模型,都可以抽象一层出来,提供一致的接口,广为人知的有ACE,Libevent这些,他们都是跨平台的,而且他们自动选择最优的I/O复用机制,用户只需调用接口即可。说到这里又得说说2个设计模式,Reactor and Proactor。有一篇经典文章值得阅读,Libevent是Reactor模型,ACE提供Proactor模型。实际都是对各种I/O复用机制的封装。
Java nio包是什么I/O机制?
我曾天真的认为java nio封装的是IOCP。。现在可以确定,目前的java本质是select()模型,可以检查/jre/bin/nio.dll得知。至于java服务器为什么效率还不错。。我也不得而知,可能是设计得比较好吧。。-_-。
=====================分割线==================================
总结一些重点:
只有IOCP是asynchronous I/O,其他机制或多或少都会有一点阻塞。 select低效是因为每次它都需要轮询。但低效也是相对的,视情况而定,也可通过良好的设计改善 epoll, kqueue是Reacor模式,IOCP是Proactor模式。 java nio包是select模型。。
Reference:
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:33365次
排名:千里之外
原创:35篇
转载:11篇
(1)(3)(5)(1)(4)(18)(9)(5)
(window.slotbydup = window.slotbydup || []).push({
id: '4740887',
container: s,
size: '250,250',
display: 'inlay-fix'博客分类:
Nepxion-Thunder(QQ 群 )发布在
1. 本地配置
如果本地配置启动,需要在XML配置config="local"
&thunder:registry id="registry" type="zookeeper" address="localhost:2181" config="local"/&
新建业务工程时候,在相关路径下新建thunder-ext.properties。配置取值的优先级顺序是thunder-ext.properties-&thunder.properties(在thunder.jar里)。如果配置名相同,取优先级高的值。它是一个集成式的配置,对于通信中间件,应用哪个就配置哪个,内容如下:
# 该项只用在hessian上,即访问Hessian Servlet的Web module
# Web module path, if that is provided as a web service
path = /thunder
# 在配置XML的时候,调用模式缺省下的默认值
# Spring XML里不配置async,即采用默认同步的方式
# Method invoke with async false, that is a default value
async = false
# 在配置XML的时候,广播模式缺省下的默认值
# Spring XML里不配置broadcast,即采用默认禁止广播方式
# Method invoke with broadcast false, that is a default value
broadcast = false
# 在配置XML的时候,同步超时时间缺省下的默认值
# Spring XML里不配置同步方法的timeout,即采用默认同步超时为30秒,如果超过30秒,同步方法没返回,就抛出超时异常
# Sync method timeout, that is a default value
syncTimeout = 30 * 1000
# 在配置XML的时候,异步超时时间缺省下的默认值
# Spring XML里不配置异步方法的timeout,即采用默认异步超时为60秒,如果超过5分钟,异步结果没回调回来,就清除异步缓存,并抛出异常
# Async method timeout, aysnc cache will be remove when timeout, that is a default value
asyncTimeout = 5 * 60 * 1000
# 异步守护线程对异步超时结果的扫描,默认10秒扫描一次,该值不能在XML里定义
# Async method scan interval, thread will start to clear timeout cache every scan interval
asyncScan = 10 * 1000
# 是否采用压缩,采用压缩其实是用少量CPU的开销,来换取网络传输的开销
# 一般来说,2KB-20KB的消息体,通过压缩传递,吞吐量TPS可以提高20%-30%;但是大数据量会增加CPU开销
# 如果采用Netty协议,它内部会有一个JdkZlib等压缩算法,可以再次压缩
# Compress transport data, maybe it works well for 2KB-20KB
compress = false
# 因网络原因(例如所有服务器挂掉)下,调用失败后,Thunder将自动采取重复调用,以保证请求不丢失。当侦测到网络原因调用失败后,会负载均衡去调用其他的服务器。
# 该项机制,只支持Netty和Hessian。MQ出现网络原因而服务调用,会自动采取重连而阻塞进程,所以没必要实现这种机制。
# Load Balance Configuration (used for Netty and Hessian)
# 是否需要重试,如果true,客户端将阻塞线程,等到服务端至少一台恢复;如果false,将直接抛出异常
loadBalanceRetry = true
# 重试次数
loadBalanceRetryTimes = 10000
# 每次重试的间隔时间
loadBalanceRetryDelay = 5 * 1000
# 是否需要异步异常事件发布通知
# If event notification is true, all produce and consume failure will be thrown out via an async event, so that will make the invocation do a retry
eventNotification = true
# 调用过程中,出现异常用邮件通知
# If event notification and smtp mail notification are all true, all produce and consume failure will be sent as a mail
# 关闭邮件通知
smtpNotification = false
# 是否负载均衡信息的打印(负载均衡信息有助于判断哪台服务器被选中),开启后,可能会造成日志量大增
# Load balance log will help to indicate which server will be selected (used for Netty and Hessian)
loadBalanceLogPrint = true
# 是否传输信息的打印(传输信息有助于判断请求发往哪台服务器,从哪台服务器响应)
# Transport log will help to indicate the transport information
transportLogPrint = true
# 是否心跳信息的打印(心跳信息有助于判断Netty数据通道是否还存活),开启后,可能会造成日志量大增
# Heart beat log will help to indicate the data channel is alive or not (used for Netty)
heartBeatLogPrint = true
# 是否序列化后字节数组压缩和未压缩等长度信息的打印(长度信息有助于判断业务对象的大小,供业务部门选择是否压缩)
# Serializer log will help to indicate the byte array length
serializerLogPrint = false
# 异常通知的白名单,一旦指定,白名单里的异常将不会通过邮件发送,用逗号分隔
# Failure Notification exclusion, use "," to separate
smtpNotificationExclusion = com.nepxion.thunder.security.SecurityException
# 是否是Ssl模式
smtpSsl = true
# 邮件服务器的地址
smtpHost =
# 发件人的账户
smtpUser = *******@qq.com
# 发件人的账户密码
smtpPassword =
# 发件人的邮件地址
smtpMailFrom = *******@qq.com
# 收件人的邮件地址列表,用逗号分隔
smtpMailTo = *******@qq.com,*******@qq.com
# 抄送的邮件地址列表,用逗号分隔
smtpMailCC =
# 暗送的邮件地址列表,用逗号分隔
smtpMailBCC =
# Thread Pool Configuration
# 线程隔离,一旦值为true,每个接口将对应一个线程池
# Multi thread pool
threadPoolMultiMode = false
# CPU unit
threadPoolServerCorePoolSize = 4
# CPU unit
threadPoolServerMaximumPoolSize = 8
threadPoolServerKeepAliveTime = 15 * 60 * 1000
threadPoolServerAllowCoreThreadTimeout = false
# CPU unit
threadPoolClientCorePoolSize = 4
# CPU unit
threadPoolClientMaximumPoolSize = 8
threadPoolClientKeepAliveTime = 15 * 60 * 1000
threadPoolClientAllowCoreThreadTimeout = false
# LinkedBlockingQueue, ArrayBlockingQueue, SynchronousQueue
threadPoolQueue = LinkedBlockingQueue
# CPU unit (Used for LinkedBlockingQueue or ArrayBlockingQueue)
threadPoolQueueCapacity = 1024
# BlockingPolicyWithReport, CallerRunsPolicyWithReport, AbortPolicyWithReport, RejectedPolicyWithReport, DiscardedPolicyWithReport
# BlockingPolicyWithReport :使用阻塞生产者的饱和策略,不抛弃任务,也不抛出异常,当队列满时改为调用BlockingQueue.put来实现生产者的阻塞
# CallerRunsPolicyWithReport :使用Caller-Runs(调用者执行)饱和策略,不抛弃任务,也不抛出异常,而是将当前任务回退到发起这个调用者执行的线程所在的上级线程去执行
# AbortPolicyWithReport :任务饱和时, 抛弃任务,抛出异常
# RejectedPolicyWithReport :如果该任务实现了RejectedRunnable接口,那么交给用户去实现拒绝服务的逻辑,否则以FIFO的方式抛弃队列中一部分现有任务,再添加新任务
# DiscardedPolicyWithReport :任务饱和时以FIFO的方式抛弃队列中一部分现有任务,再添加新任务
threadPoolRejectedPolicy = BlockingPolicyWithReport
# 对象池,主要是用于FST快速序列化实现
# FST Object Pool Configuration
# CPU unit
fstObjectPoolMaxTotal = 64
# CPU unit
fstObjectPoolMaxIdle = 32
# CPU unit
fstObjectPoolMinIdle = 16
fstObjectPoolMaxWaitMillis = 3000
fstObjectPoolTimeBetweenEvictionRunsMillis = 1000 * 60 * 15
fstObjectPoolMinEvictableIdleTimeMillis = 1000 * 60 * 30
fstObjectPoolSoftMinEvictableIdleTimeMillis = 1000 * 60 * 30
fstObjectPoolBlockWhenExhausted = true
fstObjectPoolLifo = true
fstObjectPoolFairness = false
# Netty调优
# Netty Configuration
nettySoBacklog = 128
nettySoSendBuffer = 64 * 1024
nettySoReceiveBuffer = 64 * 1024
nettyWriteBufferHighWaterMark = 32 * 1024
nettyWriteBufferLowWaterMark = 8 * 1024
nettyMaxMessageSize = 1 * 1024 * 1024
nettyWriteIdleTime = 90 * 1000
nettyReadIdleTime = 60 * 1000
nettyAllIdleTime = 45 * 1000
nettyWriteTimeout = 5 * 1000
nettyReadTimeout = 5 * 1000
nettyConnectTimeout = 10 * 1000
nettyReconnectDelay = 1000
# Hessian调优
# Hessian Configuration
hessianReadTimeout = 30 * 1000
hessianConnectTimeout = 10 * 1000
# Redis调优
# Redis Configuration
# CPU unit
redisObjectPoolMaxTotal = 30
# CPU unit
redisObjectPoolMaxIdle = 10
# CPU unit
redisObjectPoolMinIdle = 10
redisObjectPoolMaxWaitMillis = 1000 * 3
redisObjectPoolTimeBetweenEvictionRunsMillis = 1000 * 30
redisObjectPoolMinEvictableIdleTimeMillis = 1000 * 60
redisObjectPoolSoftMinEvictableIdleTimeMillis = 1000 * 60
redisObjectPoolBlockWhenExhausted = true
redisObjectPoolLifo = true
redisObjectPoolFairness = false
redisSoTimeout = 5 * 1000
redisConnectionTimeout = 5 * 1000
redisDataExpiration = 15 * 24 * 60 * 1000
# Setinel parameters
redisReconnectionWait = 5
redisDatabase = 0
# Cluster parameters
redisMaxRedirections = 5
# Splunk调优
# Splunk Configuration
splunkMaximumTime = 60
# 消息队列调优
# Kafka Configuration
kafka.producer.acks = all
kafka.producer.linger.ms = 0
kafka.producer.retries = 0
kafka.producer.buffer.memory =
kafka.producer.send.buffer.bytes = 131072
kafka.producer.receive.buffer.bytes = 32768
kafka.producer.max.request.size = 1048576
kafka.producer.batch.size = 16384
kafka.producer.timeout.ms = 30000
kafka.producer.request.timeout.ms = 30000
kafka.producer.connections.max.idle.ms = 540000
kafka.producer.reconnect.backoff.ms = 50
kafka.producer.retry.backoff.ms = 100
kafka.producer.max.block.ms = 60000
kafka.producer.max.in.flight.requests.per.connection = 5
kafka.producer.metadata.max.age.ms = 300000
kafka.producer.metadata.fetch.timeout.ms = 60000
kafka.consumer.server.poll.timeout.ms = 1000
kafka.consumer.client.poll.timeout.ms = 1000
kafka.consumer.mit = true
kafka.consumer.auto.offset.reset = latest
kafka.consumer.send.buffer.bytes = 131072
kafka.consumer.receive.buffer.bytes = 32768
kafka.consumer.max.partition.fetch.bytes = 1048576
kafka.consumer.fetch.min.bytes = 1024
kafka.consumer.fetch.max.wait.ms = 500
kafka.mit.interval.ms = 10000
kafka.consumer.heartbeat.interval.ms = 3000
kafka.consumer.session.timeout.ms = 30000
kafka.consumer.request.timeout.ms = 40000
kafka.consumer.connections.max.idle.ms = 540000
kafka.consumer.reconnect.backoff.ms = 50
kafka.consumer.retry.backoff.ms = 100
kafka.consumer.metadata.max.age.ms = 300000
# MQ Common Configuration (used for ActiveMQ and Tibco)
mqRetryNotificationDelay = 5 * 1000
mqReconnectOnException = true
# CacheConnectionFactory Configuration (used for ActiveMQ and Tibco)
mqSessionCacheSize = 20
mqCacheConsumers = true
mqCacheProducers = true
# PoolConnectionFactory Configuration (used for ActiveMQ and Tibco)
mqMaxConnections = 20
mqMaximumActiveSessionPerConnection = 100
mqIdleTimeout = 30 * 1000
mqExpiryTimeout = 0
mqBlockIfSessionPoolIsFull = true
mqBlockIfSessionPoolIsFullTimeout = -1
mqTimeBetweenExpirationCheckMillis = -1
mqCreateConnectionOnStartup = true
# DefaultMessageListenerContainer Configuration (used for ActiveMQ and Tibco)
mqConcurrentConsumers = 10
mqMaxConcurrentConsumers = 1
mqReceiveTimeout = 1000
mqRecoveryInterval = 5000
mqIdleConsumerLimit = 1
mqIdleTaskExecutionLimit = 1
mqCacheLevel = 4
mqAcceptMessagesWhileStopping = false
# Apache HttpComponent调优,作为辅助组件,支持同步和异步两种方式,可被外部调用
# Apache Configuration
apacheBacklogSize = 128
apacheSendBufferSize = 64 * 1024
apacheReceiveBufferSize = 64 * 1024
apacheSoTimeout = 5 * 1000
apacheConnectTimeout = 5 * 1000
# CPU unit
apacheMaxTotal = 32
# Zookeeper调优
# Zookeeper Configuration
zookeeperSessionTimeout = 15 * 1000
zookeeperConnectTimeout = 15 * 1000
zookeeperConnectWaitTime = 1000
# Zookeeper的连接配置,效果等同于Spring XML的&thunder:registry ... address="localhost:2181".../&
# Zookeeper Connection Configuration
zookeeperAddress = localhost:2181
# Redis的哨兵连接配置,用于Netty和Hessian的发布/订阅功能,以及日志缓存上
# Redis Sentinel Connection Configuration
redisSentinel = 192.168.126.151:8.126.151:8.126.151:36379
redisMasterName = mymaster
redisClientName =
redisPassword =
# Redis的集群连接配置,用于日志缓存上,哨兵和集群配置最好两者选其一,推荐用哨兵配置
# Redis Cluster Connection Configuration
# redisCluster = 192.168.126.131:.126.131:.126.131:.126.131:.126.131:.126.131:7006
# Splunk日志服务器配置
# Splunk Connection Configuration
splunkHost = localhost
splunkPort = 8089
splunkUserName = admin
splunkPassword = admin
# Kafka的连接配置
# Kafka Connection Configuration
kafka-1.kafka.producer.bootstrap.servers = localhost:9092
kafka-1.kafka.consumer.bootstrap.servers = localhost:9092
# ActiveMQ的连接配置
# ActiveMQ Connection Configuration
activeMQ-1.mqUrl = failover://(tcp://localhost:61616)?initialReconnectDelay=1000&jms.prefetchPolicy.all=5
# activeMQ-1.mqUrl = failover://(tcp://broker1:61616,tcp://broker2:61616)?randomize=true
# SingleConnectionFactory, CachingConnectionFactory, PooledConnectionFactory
activeMQ-1.mqConnectionFactoryType = CachingConnectionFactory
activeMQ-1.mqUserName = admin
activeMQ-1.mqPassword = admin
# activeMQ-1.mqJndiName = ConnectionFactory
# Tibco的连接配置
# Tibco Connection Configuration
tibco-1.mqUrl = tcp://localhost:7222
# SingleConnectionFactory, CachingConnectionFactory, PooledConnectionFactory
tibco-1.mqConnectionFactoryType = CachingConnectionFactory
tibco-1.mqUserName = admin
tibco-1.mqPassword =
tibco-1.mqJndiName = seashellConnectionFactory
tibco-2.mqUrl = tcp://localhost:7222
# SingleConnectionFactory, CachingConnectionFactory, PooledConnectionFactory
tibco-2.mqConnectionFactoryType = CachingConnectionFactory
tibco-2.mqUserName = admin
tibco-2.mqPassword =
tibco-2.mqJndiName = FTQueueConnectionFactory
2. 远程配置
如果本地配置启动,需要在XML配置config="remote"
&thunder:registry id="registry" type="zookeeper" address="localhost:2181" config="remote"/&
配置取值的优先级顺序是远程配置-&thunder-ext.properties-&thunder.properties(在thunder.jar里)。如何进行远程配置,参照
好東東,是否支持其它語言客戶端?
浏览: 18412 次
来自: 上海
要是搞个列表能直接跳转到相应的章节就更完美了
参考第一章,就描述了这个框架和Dubbo的一些区别,以及性能上 ...
有没有和dubbo做过比较呢。
birdhur 写道很不错的框架,值得好好学习,赞谢谢!最近有 ...Posts - 36,
Articles - 3,
Comments - 1
09:12 by zhaoyang10, ... 阅读,
  1.主机和设备间异步执行
  为了易于使用主机和设备间的异步执行,一些函数是异步的:在设备完全完成任务前,控制已经返回给主机线程了。它们是: 内核发射; 设备间数据拷贝函数; 主机和设备内拷贝小于64KB的存储器块时; 存储器拷贝函数中带有Async后缀的; 设置设备存储器的函数调用。
  程序员可通过将CUDA_LAUNCH_BLOCKING环境变量设置为1来全局禁用所有运行在系统上的应用的异步内核发射。提供这个特性只是为了调试,永远不能作为使软件产品运行得可靠的方式。 当应用通过CUDA调试器或CUDA profiler(cuda-gdb, CUDA Visual Profiler, Parallel Nsight)运行时,所有的内核发射都是同步的。
  2.数据传输和内核执行重叠
  一些计算能力1.1或更高的设备可在内核执行时,在分页锁定存储器和设备存储器之间拷贝数据。应用可以通过检查asyncEngineCount 设备属性查询这种能力,如果其大于0,说明设备支持数据传输和内核执行重叠。这种能力目前只支持不涉及CUDA数组和使用cudaMallocPitch()分配的二维数组的存储器拷贝( 见前文,可阅读&相关阅读&中的文章)。
  3. 并发内核执行
  一些计算能力2.x的设备可并发执行多个内核。应用可以检查concurrentKernels属性以查询这种能力)(后续文章将介绍),如果等于1,说明支持。 设备最大可并发执行的内核数目是16。 来自不同CUDA上下文的内核不能并发执行。 使用了许多纹理或大量本地存储器的内核和其它内核并发执行的可能性比较小。
  4. 并发数据传输
  在计算能力2.x的设备上,从主机分页锁定存储器复制数据到设备存储器和从设备存储器复制数据到主机分页锁定存储器,这两个操作可并发执行。 应用可以通过检查asyncEngineCount 属性查询这种能力,如果等于2,说明支持。
  应用通过流管理并发。流是一系列顺序执行的命令(可能是不同的主机线程发射)。另外,流之间相对无序的或并发的执行它们的命令;这种行为是没有保证的,而且不能作为正确性的的保证(如内核间的通信没有定义)。
  ①创建和销毁
  可以通过创建流对象来定义流,且可指定它作为一系列内核发射和设备主机间存储器拷贝的流参数。下面的代码创建了两个流且在分页锁定存储器中分配了一个名为hostPtr的浮点数组。
cudaStream_t stream[2];
for&(int&i&=&0; i&&&2;&++i)
cudaStreamCreate(&stream[i]);
float*&hostP
cudaMallocHost((void**)&hostPtr,&2&*&size);
&  下面的代码定义的每个流是一个由一次主机到设备的传输,一次内核发射,一次设备到主机的传输组成的系列。
for&(int&i&=&0; i&&&2;&++i){ cudaMemcpyAsync(inputDevPtr&+&i&*&size, hostPtr&+&i&*&size, size, cudaMemcpyHostToDevice, stream[i]); MyKernel&&&100,&512,&0, stream[i]&&&&(outputDevPtr&+&i&*&size, inputDevPtr&+&i&*&size, size); cudaMemcpyAsync(hostPtr&+&i&*&size, outputDevPtr&+&i&*&size, size, cudaMemcpyDeviceToHost, stream[i]); }
  每个流将它的hostPtr输入数组的部分拷贝到设备存储器数组inputdevPtr,调用MyKernel()内核处理inputDevPtr,然后将结果outputDevPtr传输回hostPtr同样的部分。后文描述了例子中的流如何依赖设备的计算能力重叠。必须注意为了使用重叠hostPtr必须指向分页锁定主机存储器。
  调用cudaStreamDestroy()来释放流。
for&(int&i&=&0; i&&&2;&++i)
&cudaStreamDestroy(stream[i]);
&  cudaStreamDestroy()等待指定流中所有之前的任务完成,然后释放流并将控制权返回给主机线程。
  ② 默认流
  内核启动和没有使用流参数的主机设备间数据拷贝,或者等价地将流参数设为0,此时发射到默认流。因此顺序执行。
  ③显式同步
  有很多方法显式的在流之间同步。
  cudaDeviceSynchronize()直到前面所有流中的命令都执行完。
  cudaStreamSynchronize()以某个流为参数,强制运行时等待该流中的任务都完成。可用于同步主机和特定流,同时允许其它流继续执行。
  cudaStreamWaitEvent()以一个流和一个事件为参数(后文将介绍),使得在调用cudaStreamWaitEvent()后加入到指定流的所有命令暂缓执行直到事件完成。流可以是0,此时在调用cudaStreamWaitEvent()后加入到所有流的所有命令等待事件完成。
  cudaStreamQuery()用于查询流中的所有之前的命令是否已经完成。
  为了避免不必要的性能损失,这些函数最好用于计时或隔离失败的发射或存储器拷贝。
  ④隐式同步
  如果是下面中的任何一种情况,来自不同流的两个命令也不能并发:分页锁定主机存储器分配,设备存储器分配,设备存储器设置,设备之间存储器拷贝,默认流中调用的任何CUDA命令, F.4.1节描述的一级缓存/共享存储器之间配置切换。
  对于支持并发内核执行的设备,任何需要依赖检测以确定内核发射是否完成的操作:
  1)只有来自CUDA上下文中的任何流中的所有的前面的内核启动的线程块开始执行,才能够开始执行;
  2)会阻塞CUDA上下文中后面任何流中所有的内核发射直至被检测的内核发射完成。
  需要依赖检测的操作包括同一个流中的一些其它类似被检查的发射的命令和流中的任何cudaStreamQuery()调用。因此,应用应当遵守这些指导以提升潜在的内核并发执行:
  1)所有独立操作应当在依赖操作之前发出,
  2)任何类型同步尽量延后。
  ⑤重叠行为
  两个流的重叠执行数量依赖于发射到每个流的命令的顺序和设备是否支持数据传输和内核执行重叠、并发内核执行、并发数据传输。
  例如,在不支持并发数据传输的设备上,前面例程的两个流并没有重叠,因为发射到流1的从主机到设备的存储器拷贝在发射到流0的从设备到主机的存储器拷贝之后,因此只有发射到流0的设备到主机的存储器拷贝完成它才开始。如果代码重写成如下方式(同时假设设备支持数据传输和内核执行重叠)。
for&(int&i&=&0; i&&&2;&++i)
cudaMemcpyAsync(inputDevPtr&+&i&*&size, hostPtr&+&i&*&size, size, cudaMemcpyHostToDevice, stream[i]);
for&(int&i&=&0; i&&&2;&++i)
MyKernel&&&100,&512,&0, stream[i]&&&&(outputDevPtr&+&i&*&size, inputDevPtr&+&i&*&size, size);
for&(int&i&=&0; i&&&2;&++i)
cudaMemcpyAsync(hostPtr&+&i&*&size, outputDevPtr&+&i&*&size, size, cudaMemcpyDeviceToHost, stream[i]);
  此时发射到流1的从主机到设备的存储器拷贝和发射到流0的内核执行重叠。
  在支持并发数据传输的设备上,前文例程的两个流重叠:发射到流1的从主机到设备的存储器拷贝和发射到流0的设备到主机的存储器拷贝,甚至和发射到流0的内核执行(假设设备支持数据传输和内核执行重叠)。但是内核执行不可能重叠,因为发射到流1的第二个内核执行在发射到流0的设备到主机的存储器拷贝之后,因此会被阻塞直到发射到流0的内核执行完成。如果代码被重写成上面的样子,内核执行就重叠了(假设设备支持并发内核执行),因为发射到流1的第二个内核执行在发射到流0的设备到主机的存储器拷贝之前。然而在这种情况下,发射到流0的设备到主机的存储器只和发射到流1的内核执行的最后一个线程块重叠,这只占总内核执行时间的一小部分。
  6.事件
  通过在应用的任意点上异步地记载事件和查询事件是否完成,运行时提供了精密地监测设备运行进度和精确计时。当事件记载点前面,事件指定的流中的所有任务或者指定流中的命令全部完成时,事件被记载。只有记载点之前所有的流中的任务/命令都已完成,0号流的事件才会记载。
  ①创建和销毁
  下面的代码创建了两个事件:
cudaEvent_t start, cudaEventCreate(&start); cudaEventCreate(&stop);
&  以下面的方式销毁它们:
cudaEventDestroy(start); cudaEventDestroy(stop);
&  ②过去的时间
  节建立的事件可以用下面的方式给3.2.5.5.1节的代码计时:
cudaEventRecord(start,&0); for&(int&i&=&0; i&&&2;&++i){ cudaMemcpyAsync(inputDev&+&i&*&size, inputHost&+&i&*&size, size, cudaMemcpyHostToDevice, stream[i]); MyKernel&&&100,&512,&0, stream[i]&&&&(outputDev&+&i&*&size, inputDev&+&i&*&size, size); cudaMemcpyAsync(outputHost&+&i&*&size, outputDev&+&i&*&size, size, cudaMemcpyDeviceToHost, stream[i]); cudaEventRecord(stop,&0); cudaEventSynchronize(stop); float&elapsedT cudaEventElapsedTime(&elapsedTime, start, stop);
&  7.同步调用
  直到设备真正完成任务,同步函数调用的控制权才会返回给主机线程。在主机线程执行任何其它CUDA调用前,通过调用cudaSetDeviceFlags()并传入指定(参见参考手册)可以指定主机线程的让步,阻塞,或自旋状态。
&&&&&&& 更多内容请点击:
&&&&&&& CUDA专区:
&&&&&&& CUDA论坛:

我要回帖

更多关于 blockingdeque 的文章

 

随机推荐