jjzjj

Linux drm内存管理(一) 浅谈TTM与GEM,为什么我们需要TTM和GEM?

不想好好取名字 2024-05-19 原文

@[TOC](Linux drm内存管理(一) 为什么我们需要TTM和GEM?)

系列文章(更新中):
Linux drm内存管理(二) TTM内存管理基础概念

前言

  目前Kernel中DRM中GPU的VRAM(GPU片上显存)的管理框架是有GEM和TTM,其中TTM早于GEM出现,GEM的出现是为了解决TTM复杂的使用方法,将大部分的VRAM管理实现逻辑交由厂商实现。

正文

  如果你看了何总的GEM相关的博客,我这里额外补充一点我了解到的知识点,我们都知道了内核层的GEM指向或者说包含一片内存,应用层只能获取到GEM的handle,但是可以通过mmap获取到内核层GEM所指向的内存,从而实现CPU读写。
  GPU可以使用自己的片上显存,同时也能使用CPU的内存。假设我们GEM指向的内存都在GPU的片上显存上,那我们多次创建和释放GEM,片上显存是如何实现管理的?比如第一个GEM指向的是GPU的0-16MB,第二个GEM指向的是16-32MB,第三个GEM指向的是CPU的某块内存。很明显GEM只能负责完成内存的映射,我们额外需要一个管理GEM的框架去管理显存的分配,或者说我们需要一个框架去统一GPU的内存寻址总线

思考

  我看GEM和TTM还有AMD DRM的源码一直在思考一个问题,为什么要创建GEM\TTM框架去管理GPU的VRAM?
  我们都知道CPU的内存 在Linux中通过伙伴系统进行管理,为什么GPU不能简单套用CPU的内存管理子系统,而要额外创建GEM和TTM框架来管理GPU的VRAM?
  CPU 使用内存的方法:直接用alloc_pages向伙伴系统申请page,伙伴系统找一片空闲的内存返回,或者通过slab\slub\CMA\shmem等子系统间接申请page,申请成功后再对这些page进行读写。
  GPU和CPU类似,想办法在显存中找一片空闲的区域,成功找到后再对这片区域读写。共同点都是申请一片内存区域,然后读写使用,为什么GPU要用GEM和TTM进行管理呢?
根本原因上面提到过,GPU的内存总类很多,寻址总线无法统一

GPU使用内存相比CPU有以下缺点

1.GPU的内存种类多
  GPU有独显也有核显,核显借用CPU的RAM当作VRAM,独显有着自己的VRAM,当然也可以借用CPU的RAM当作VRAM,GPU的内存种类多,既能访问自己的显存,也能访问CPU的内存,GPU的内存总线没有统一,不同的bus访问方式甚至物理属性不同(解释下属性不同:如果Texture放RAM中,S3睡眠的时候内存是不断电的,如果Texture放VRAM中,S3睡眠数据全丢了),所以CPU内存管理框架无法运用在GPU上。

2.CPU与GPU之间带宽有限
  内存直接挂在CPU的地址和数据总线上,CPU访问自己的内存很简单。
  GPU一般是挂在CPU的外设总线上例如PCIE上,所以GPU的VRAM地址需要映射后访问。CPU和GPU不是直连,通讯带宽是有限的,我们当然可以通过将IO映射到总线上来,通过MMIO直接进行数据传输,但是访问会不断的触发外设的数据传输,而CPU和GPU的带宽肯定没有CPU和内存之间的带宽大,最好还是得借助老朋友DMA,去节省有限的带宽

3.GPU的内存使用方式与CPU不同
  GPU的使用上,往往使用一片显存作为最小使用单位,例如一个Texture,Shader,而非单个字节做为最小单位。实际上对于应用层来说,我们不关心Texture被分配会在显存的哪个位置,也不关心Texture是如何分配的,所以我们建立Buffer Object(BO)的概念,作为GPU显存使用的最小单位。

  综上,这就是GPU内存管理框架产生的原因,我们需要一套框架去管理BO的分配与释放,这套内存管理框架和核心思想:应用层并不需要在乎我们BO被分配在哪,但是内核层需要去处理GPU不同的bus,将bo放在合适的位置(例如VRAM或者是CPU的RAM)

TTM与GEM有什么不同

  TTM是用GEM的实现内存管理框架(AMD提出),GEM一般被GPU厂商嵌入自己的数据结构,构造自己的内存管理框架。

BO主要的应用场景实现区别

1.BO需要从VRAM 转移到 RAM,或者是从RAM转移到VRAM。(TTM提供实现接口)
2.BO需要将指向的内存映射出来,供应用层CPU访问。(TTM/GEM提供实现接口)
所以说TTM要比GEM复杂。

有关Linux drm内存管理(一) 浅谈TTM与GEM,为什么我们需要TTM和GEM?的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  3. ruby - i18n Assets 管理/翻译 UI - 2

    我正在使用i18n从头开始​​构建一个多语言网络应用程序,虽然我自己可以处理一大堆yml文件,但我说的语言(非常)有限,最终我想寻求外部帮助帮助。我想知道这里是否有人在使用UI插件/gem(与django上的django-rosetta不同)来处理多个翻译器,其中一些翻译器不愿意或无法处理存储库中的100多个文件,处理语言数据。谢谢&问候,安德拉斯(如果您已经在ruby​​onrails-talk上遇到了这个问题,我们深表歉意) 最佳答案 有一个rails3branchofthetolkgem在github上。您可以通过在Gemfi

  4. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  5. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  6. ruby - 在 64 位 Snow Leopard 上使用 rvm、postgres 9.0、ruby 1.9.2-p136 安装 pg gem 时出现问题 - 2

    我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po

  7. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  8. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  9. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

    为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

  10. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

随机推荐