当前位置: 首页 > news >正文

网站下载不了视频宁波seo软件免费课程

网站下载不了视频,宁波seo软件免费课程,网站建设与制作企业,员工管理系统源码网上介绍了很多局部性原理的好处,本文结合笔者最近的遭遇,简单的做个分享。 局部性原理就不介绍了,下面直接上例子。 我们以linux内核v6.15的函数collect_longterm_unpinnable_folios为例,这里简单的假设没有启用HVO特性。 stati…

网上介绍了很多局部性原理的好处,本文结合笔者最近的遭遇,简单的做个分享。
局部性原理就不介绍了,下面直接上例子。
我们以linux内核v6.15的函数collect_longterm_unpinnable_folios为例,这里简单的假设没有启用HVO特性。

static inline const struct page *page_fixed_fake_head(const struct page *page)
{return page;
}static __always_inline unsigned long _compound_head(const struct page *page)
{unsigned long head = READ_ONCE(page->compound_head);if (unlikely(head & 1))return head - 1;return (unsigned long)page_fixed_fake_head(page);
}#define page_folio(p)		(_Generic((p),				\const struct page *:	(const struct folio *)_compound_head(p), \struct page *:		(struct folio *)_compound_head(p)))static struct folio *pofs_get_folio(struct pages_or_folios *pofs, long i)
{if (pofs->has_folios)return pofs->folios[i];return page_folio(pofs->pages[i]);
}static unsigned long collect_longterm_unpinnable_folios(struct list_head *movable_folio_list,struct pages_or_folios *pofs)
{unsigned long i, collected = 0;struct folio *prev_folio = NULL;bool drain_allow = true;for (i = 0; i < pofs->nr_entries; i++) {struct folio *folio = pofs_get_folio(pofs, i);if (folio == prev_folio)continue;prev_folio = folio;*********
}

简单解释一下函数的逻辑,pofs是一个数组,数组长pofs->nr_entries,这个数组是由gup接口,通过页表,按PAGE_SIZE的步长,获取到的由用户传入的一个虚拟地址范围里对应的page/folio,函数collect_longterm_unpinnable_folios的目的就是筛选出这个数组里的page/folio是否属于“longterm_unpinnable”。逻辑非常简单,遍历数组,然后检查。
这个函数的逻辑没有什么问题,但现如今程序为了提升性能,会尽可能的使用大页(THP或者HUGETLBFS),当gup接口碰到这种情况的时候,pofs里相邻的page其实就是属于同一个large folio,这种情况下,就为局部性原理带来了可施展的空间。
那具体怎么施展的呢?
先放上优化后的代码,再做分析。

@@ -2296,6 +2296,31 @@ static void pofs_unpin(struct pages_or_funpin_user_pages(pofs->pages, pofs->nr_entries);}+static struct folio *pofs_next_folio(struct folio *folio,
+                struct pages_or_folios *pofs, long *index_ptr)
+{
+        long i = *index_ptr + 1;
+
+        if (!pofs->has_folios && folio_test_large(folio)) {
+                const unsigned long start_pfn = folio_pfn(folio);
+                const unsigned long end_pfn = start_pfn + folio_nr_pages(folio);
+
+                for (; i < pofs->nr_entries; i++) {
+                        unsigned long pfn = page_to_pfn(pofs->pages[i]);
+
+                        /* Is this page part of this folio? */
+                        if (pfn < start_pfn || pfn >= end_pfn)
+                                break;
+                }
+        }
+
+        if (unlikely(i == pofs->nr_entries))
+                return NULL;
+        *index_ptr = i;
+
+        return pofs_get_folio(pofs, i);
+}
+/** Returns the number of collected folios. Return value is always >= 0.*/
@@ -2303,16 +2328,12 @@ static void collect_longterm_unpinnable_struct list_head *movable_folio_list,struct pages_or_folios *pofs){
-        struct folio *prev_folio = NULL;bool drain_allow = true;
-        unsigned long i;
+        struct folio *folio;
+        long i = 0;-        for (i = 0; i < pofs->nr_entries; i++) {
-                struct folio *folio = pofs_get_folio(pofs, i);
-
-                if (folio == prev_folio)
-                        continue;
-                prev_folio = folio;
+        for (folio = pofs_get_folio(pofs, i); folio;
+                 folio = pofs_next_folio(folio, pofs, &i)) {if (folio_is_longterm_pinnable(folio))continue;

我们看原始collect_longterm_unpinnable_folios()函数循环体里面,每次循环获取一个folio,然后与prev_folio做比较,相同则跳过。
从pofs_get_folio()函数的实现就可以发现,如果我们将这个比较放进pofs_get_folio()函数函数中,那就可以省去不少if (pofs->has_folios)的判断了,由此带来的第一个优化点,就是branch数的减少,从而能够提升cache/tlb的命中率。
继续深入探究,page_folio()的实现,本质是调用了_compound_head(),这个函数的第一行就是一个READ_ONCE(),根据文章https://quant67.com/post/linux/access_once.html 我们知道,这是一个阻碍编译器做优化的函数,并且使用了READ_ONCE()之后,数据必须从内存/cache中去获取,而不能将其暂存在寄存器里,笔者简单试了一下,将这里的READ_ONCE去掉,gup接口能有不足5%的提升(可能只有1%,性能测试结果一直在波动,但是都是正向的。想想一行代码就影响了一个那么复杂的函数的性能就可怕),当然这里的READ_ONCE()肯定不能删掉,而是尝试去减少对他的调用,这是第二个优化点。
那怎么优化掉呢?本质上,也就是需要识别,下一个page,是否和当前page属于同一个large folio,那这简单,我们可以通过pfn就可以实现,large folio是一个大页,其物理地址肯定是连续的,那我们就可以看看下一个page是否属于这个物理地址范围就可以了。
从而接下来的优化就水到渠成了,我们把if (folio == prev_folio)给“搬进”函数pofs_get_folio(),只需要不断的获取下一个page的pfn,并进行判断即可。如果下一个page的pfn属于当前large folio的物理地址范围,那显然if (folio == prev_folio)成立,可以继续检查后一个page,否则,不属于这个large folio,需要做是否是longterm_unpinnable的检查。可以看到,如果我们遇到了连续的page属于同一个large folio,我们的代码就是读取数组下一个成员,并做一个简单的if判断,接着下一个成员做判断,这样不断地循环,函数的主要流程就能收缩在这两个连续的指令,这就是典型的使用局部性原理来优化程序,这是优化点三
那么,原先代码里的if (folio == prev_folio),就不属于局部性原理的优化了吗?当然属于,prev_folio是上一次访问的folio,如果运气好,肯定还在cache里,就可以很迅速地访问到。但是,鉴于pofs_get_folio()实现的较为复杂,有好几层调用,这样编译器可能就无法充分发挥其优化,并且,对于cache/tlb buffer比较小的cpu,可能因为较长的函数调用链,就会把本来想利用的局部性原理的数据/cache给冲掉了,从而对性能有较大的折扣。而这个优化的方案,相当于是把局部性原理做的更极致了而已。

http://www.cadmedia.cn/news/6380.html

相关文章:

  • 网站建设费的摊销年限网站模版
  • dw网站开发环境郑州网络营销学校
  • 亚马逊企业网站建设山西seo
  • 网站每天做100个外链重庆网站建设外包
  • 森动网网站建设好吗下载百度官方版
  • 在百度上建网站怎么建设app地推网
  • 文字变形logo设计seo常用优化技巧
  • 北京猎梦网站建设域名查询网站入口
  • 广告网站设计方案seo投放营销
  • 网站和新媒体建设管理办法百度推广最近怎么了
  • 网站建设资金方案网店运营工资一般多少
  • wordpress多个站点搜索引擎营销的特点
  • java开发网站快速提升关键词排名软件
  • 网站定制公司哪家最权威请输入搜索关键词
  • 网页站点什么意思淘宝的17种免费推广方法
  • 北京英文网站建设的原则郴州网站建设推广公司
  • 如何做网站海报账号权重查询入口
  • 网站空间流量不够西安网站制作推广
  • 网页设计与制作课程小结seo自己怎么做
  • ai写作网站以下属于网站seo的内容是
  • 制作器抖音seo是什么
  • 广西城乡建设厅网站企业文化标语
  • 如何新建一个网页页面seo综合查询爱站
  • 企业网站查询系统官网如何自己创建网址
  • 国内重大新闻2021搜索引擎优化的名词解释
  • 域名dns解析和网站建设电商产品推广方案
  • 重庆建设门户网站semi认证
  • 萧山网seo排名赚靠谱吗
  • 辽宁网站建设价位web网页制作成品免费
  • 做公司网站需要制作内容为什么不能去外包公司