- 金属破碎机
- 破石机
- 石头破碎机
- 颚式破碎机
- 反击式破碎机
- 锤式破碎机
- 复合式破碎机
- 冲击式破碎机
- 立式复合破碎机
- 重锤式破碎机
- 花岗岩石破碎机
- 高效破碎机
- 双齿破碎机
- 煤矸石破碎机
- 四辊破碎机
- 环锤式破碎机
- 小型破碎机
- 双轴破碎机
- 单辊式破碎机
- 对辊式破碎机
- 圆锥式破碎机
- 振动给料机
- 圆振动筛
- 斗式提升机
- 直线振动筛
- 电磁振动给料机
- 滚筒筛沙机
- 高频筛
- 振动筛
- 滚筒洗石机
- 干式磁选机
- 螺旋溜槽
- 螺旋分级机
客户购机前,企业免费派工程技术人员到用户现场为用户规划场地、...
- 反向回答一波,其实Async这个东西,性能上的坑是很大的,以前还是萌新的时候踩进去并绕过了这个坑(当然和十大正规网投平台自己对语言和.Net框架的理解不足也有关,各位看客当个笑话即可)。。十大正规网投平台要实现的需求是在Unity3D中对大地形的一些细小的物体实行有层级的剔除方法。熟悉这个游戏引擎的朋友可能知道,Unity3D自带的渲染管线对开放大地形的一些支撑和优化并不到位,所以需要开发者自己造轮子填坑。十大正规网投平台需要对树木,灌木,草坪,小石块等一些小物体进行动态的分组剔除,然后再精确到每组中的每个物体的剔除,最后按照其到摄像机的距离,添加到几个并行的二叉树中并实现并行排序。中间还要涉及到对不同距离的物体实行不同的LOD,以及一些场景互动的可扩展性的预留(比如场景动态破坏,物理效果)等等,这些算法任菏笳嫱镀教ɑ个部分产生GC压力或者额外开销都是不可以被接受的。在了解了新C#的异步特性以后,十大正规网投平台就开始写了不少异步方法,异步调用架构,前期只是实现简单的树状剔除和排序,用await调用一些lambda表达式,当时并不熟悉C#的lambda,以为它应该是和C++的lambdatemplate一样自动引用内联函数的指针值,或者和std::function一样即插即用,当然后来知道Delegate的内存开支是很可观的,这个算是1号坑。Task本身或其带来的一些扩展操作也会产生GC压力,这个算是2号坑。同时,线程池的设计思想在十大正规网投平台看来更像是“为了某个轻量级的当场触发的任务,触发完就没事了”设计的,而不是“需要分配并令其按顺序实行的,给每个核心的任务队列”设计的,这就导致频繁的调用本身也会带来开关线程的消耗,最后结果就是本来计划几十万数据的处理时间限制在1ms之内(因为如果游戏要达到100FPS,那么实际上留给每帧的时间总共就只有10ms),而实际则一直在2ms到5ms之内上下跳动,最高到5ms是因为GC触发的原因。后来只能彻底放弃awaitTask,使用一套自己控制的线程组,使用单例管理模式或组件模式统一触发,并使用ResetEvent保证队列之间依赖关系,虽然不说效率很高,起码已经达到了预期并且远高于asyncawait那一套了。当然咯后来引擎本身提供了一套JobSystem来实现多线程并行,实现思想和十大正规网投平台当初的实现差不多,而且性能上也有了诸多优化,后来Benchmark表明性能与NativeC++相差无几,也算是有了一个比较满意的结局。。所以经过这次波折,十大正规网投平台也算是收获了几个教训:对于C#的这些“优雅”“高级”的特性,使用一定慎之又慎,在使用时,一腚,一腚要紧盯性能曲线,多做压力测试,有问题当场干掉,不要留坑。.Net架构在许多地方对GC问题极不重视,然而千里之堤毁于蚁穴,问题攒到最后哭的是自己。盲目追求“高级”不可取,许多程序员,尤其是年轻一代的程序员(实际上十大正规网投平台本人也才刚20+,也算“年轻一代”之一#手动斜眼#),总认为新的,高级的就应该多接受,甚至还有“现在电脑硬件那么好不差这一点性能”这样荒谬的说法,这样的做法无疑是每天在自己脚下挖一撮土,挖到最后变成一个大坑了自己也出不去了……补充一下吧,首先呢十大正规网投平台说的应用方向肯定是对性能有高要求的研究方向,对性能要求不高的开发领域当然就不在十大正规网投平台讨论的范畴内了。说到异步,在开发过程中异步和并行多线程的概念确定一定是要分开的。比如网络IO一般属于低消耗但是长等待的,这种情况下可以开asyncthread让其始终处于等待状态,而一些任务,比如之前提到的剔除排序,基本都是需要高度并行+同步的。结果不可能等待(没有人会想要在几秒钟之后看到当前游戏的这一帧),这种情况下启动线程看起来就是一种很愚蠢的做法了,甚至开线程本身的消耗比运算还要高。在Intel的PPT中,不止一次的提到了JobScheduler和CommandBuffer这些字眼,也就是将需要实行的任务提前分配好,线程也提前开好并等待,任务与任务之间使用链式关系连接,保证上一条结束之前下一条不会开始实行,防止出现冲突。这样做的好处在于只需要启动一次或寥寥几次线程,把所有的任务攒到一起实行,同时对于并行逻辑,实行的方法一样(比如都是来自同一个Interface),可以使用SIMD等方法进行优化。这样做可以说已经保证了并行时超高的性能,然而还是有几点需要注意一下。为什么要用多线程?当然,充分利用的多线程肯定比单线程要快,然而十大正规网投平台想说的是为什么不用并行能力更高的设备,比如GPGPU/CUDA来运算?因此需要编写并行逻辑时要考虑这个逻辑是否对灵活性有足够高的要求,必须用CPU而不是其他设备。尽可能使用非托管资源。除了让人咬牙切齿捶胸顿足的GC问题,托管资源还存在使用指针访问时的不安全隐患以及编辑器本身的诸多限制。C#7.x的新特性比如returnref,unmanaged类型,再加上已经比较成熟的unsafe,是完全可以自己导入一套库手动进行memoryallocate的,如果没有现成的,自己用C++导出一个dll也是分分钟的事(大一C语言总学过吧23333)。保证数据紧凑性,当CPU并发多线程飙起来以后,CPU缓存的压力成倍增加,这种情况下十大正规网投平台就应该尽可能保证数据紧凑。配合上一条说过的非托管资源,当十大正规网投平台有数种来自五湖四海的不同的数据时,直接newXXX[]显然是对缓存不友好的办法。而自己手动malloc并计算指针偏移,同时计算好系统线程数与并行任务数的比例,保证同一个线程内尽可能使用相对连续的一段数据,最大限度的降低cachemiss。Dataorienteddesign,配合2,3条,在需要并行时传统面向对象的方法很容易产生缓存不友好的情况,这种时候统一调用,统一管理数据,分离数据与逻辑看起来会是更好的主意
C中async关键字到底起什么作用
2019-11-05 17:50:21
- 上一条:上一篇:不请私教如何能尽可能做到健身时动作标准
- 下一条:下一篇:KingdomRushFrontiers为什么换了一个开发商了