关于我们

质量为本、客户为根、勇于拼搏、务实创新

< 返回新闻公共列表

C#中,async关键字具体起什么作用?

发布时间:2020-01-21 17:13:51

对于C#的这些“优雅”“高级”的特性,使用一定慎之又慎,在使用时,一腚,一腚要紧盯性能曲线,多做压力测试,有问题当场干掉,不要留坑。

.Net架构在许多地方对GC问题极不重视,然而千里之堤毁于蚁穴,问题攒到最后哭的是自己。

盲目追求“高级”不可取,许多程序员,尤其是年轻一代的程序员(实际上我本人也才刚20+,也算“年轻一代”之一#手动斜眼#),总认为新的,高级的就应该多接受,甚至还有“现在电脑硬件那么好不差这一点性能”这样荒谬的说法,这样的做法无疑是每天在自己脚下挖一撮土,挖到最后变成一个大坑了自己也出不去了……

补充一下吧,首先呢我说的应用方向肯定是对性能有高要求的研究方向,对性能要求不高的开发领域当然就不在我们讨论的范畴内了。说到异步,在开发过程中异步和并行多线程的概念确定一定是要分开的。比如网络IO一般属于低消耗但是长等待的,这种情况下可以开async thread 让其始终处于等待状态,而一些任务,比如之前提到的剔除排序,基本都是需要高度并行+同步的。结果不可能等待(没有人会想要在几秒钟之后看到当前游戏的这一帧),这种情况下启动线程看起来就是一种很愚蠢的做法了,甚至开线程本身的消耗比运算还要高。

在Intel的PPT中,不止一次的提到了Job Scheduler和Command Buffer这些字眼,也就是将需要执行的任务提前分配好,线程也提前开好并等待,任务与任务之间使用链式关系连接,保证上一条结束之前下一条不会开始执行,防止出现冲突。这样做的好处在于只需要启动一次或寥寥几次线程,把所有的任务攒到一起执行,同时对于并行逻辑,执行的方法一样(比如都是来自同一个Interface),可以使用SIMD等方法进行优化。

这样做可以说已经保证了并行时超高的性能,然而还是有几点需要注意一下。

为什么要用多线程?当然,充分利用的多线程肯定比单线程要快,然而我想说的是为什么不用并行能力更高的设备,比如GPGPU/CUDA来运算?因此需要编写并行逻辑时要考虑这个逻辑是否对灵活性有足够高的要求,必须用CPU而不是其他设备。

尽可能使用非托管资源。除了让人咬牙切齿捶胸顿足的GC问题,托管资源还存在使用指针访问时的不安全隐患以及编辑器本身的诸多限制。C# 7.x的新特性比如return ref,unmanaged类型,再加上已经比较成熟的unsafe,是完全可以自己导入一套库手动进行memory allocate的,如果没有现成的,自己用C++导出一个dll也是分分钟的事(大一C语言总学过吧23333)。

保证数据紧凑性,当CPU并发多线程飙起来以后,CPU缓存的压力成倍增加,这种情况下我们就应该尽可能保证数据紧凑。配合上一条说过的非托管资源,当我们有数种来自五湖四海的不同的数据时,直接new XXX[]显然是对缓存不友好的办法。而自己手动malloc并计算指针偏移,同时计算好系统线程数与并行任务数的比例,保证同一个线程内尽可能使用相对连续的一段数据,最大限度的降低cache miss。

Data oriented design,配合2,3条,在需要并行时传统面向对象的方法很容易产生缓存不友好的情况,这种时候统一调用,统一管理数据,分离数据与逻辑看起来会是更好的主意



/template/Home/Zkeys/PC/Static