计算机组成原理:DMA
引入
過去幾年里,整個計算機產(chǎn)業(yè),都在嘗試不停地提升IO設備的速度。但是,無論IO速度怎么提升,比如CPU,總還是太慢。SSD 硬盤的 IOPS 可以到 2 萬、4 萬,但是我們 CPU 的主頻有 2GHz 以上,也就意味著每秒會有 20 億次的操作。
如果我們對于IO的操作,都是由CPU發(fā)出對應的指令,然后等待IO設備完成操作之后返回,那CPU就會有大量的時間其實都是在等待IO設備完成操作。
但是,這個CPU的等待,在很多時候,其實并沒有太多的實際意義。我們對于IO設備的大量操作,其實都只是把內存里面的數(shù)據(jù),傳輸?shù)絀O設備而已。在這種情況下,其實CPU只是在傻等而已。特別是當傳輸?shù)臄?shù)據(jù)量比較大的時候,比如進行大文件復制,如果所有數(shù)據(jù)都要經(jīng)過CPU,實在是太浪費時間了。
因此,計算機工程師們,就發(fā)明了 DMA 技術,也就是直接內存訪問(Direct MemoryAccess)技術,來減少CPU等待的時間
DMA,一個協(xié)處理器
本質上,DMA技術就是我們在主板上放一塊獨立的芯片。在進行內存和IO設備的數(shù)據(jù)傳輸?shù)臅r候,我們不再通過CPU來控制數(shù)據(jù)傳輸,而是直接通過DMA控制器(DMA Controller,簡稱 DMAC)。這塊芯片,我們可以認為它其實就是一個協(xié)處理器(Co-Processor)。
DMAC最有價值的地方體現(xiàn)在,當我們要傳輸?shù)臄?shù)據(jù)特別大、速度特別快,或者傳輸?shù)臄?shù)據(jù)特別小、速度特別慢的時候
比如說,我們用千兆網(wǎng)卡或者硬盤來傳輸大量數(shù)據(jù)時,如果都用CPU來搬運,可能忙不過來,所以可以選擇DMAC。而當數(shù)據(jù)傳輸很慢的時候,DMAC可以等數(shù)據(jù)到齊了,再發(fā)送信號,給到CPU去處理,而不會讓CPU在那里忙等待。
DMAC 是一塊“協(xié)處理器芯片”,這里的“協(xié)”,指的是"協(xié)助"CPU,完成對應的數(shù)據(jù)傳輸工作。在DMAC控制數(shù)據(jù)傳輸?shù)倪^程中,我們還是需要CPU的。
除此之外,DMAC也是一個特殊的IO設備。它和CPU以及其他IO設備一樣,通過連接到總線來進行實際的數(shù)據(jù)傳輸。總線上的設備呢,其實有兩種類型。一種我們稱之為主設備(Master),另外一種,我們稱之為從設備(Slave)。
- 想要主動發(fā)起數(shù)據(jù)傳輸,必須要是一個主設備來可以,CPU就是主設備。而我們從設備(比如硬盤)只能接收數(shù)據(jù)傳輸。
- 所以,如果通過CPU來傳輸數(shù)據(jù),要么是CPU從IO設備讀數(shù)據(jù),要么是CPU向IO設備寫數(shù)據(jù)。
那我們的 I/O 設備不能向主設備發(fā)起請求么?可以是可以,不過這個發(fā)送的不是數(shù)據(jù)內容,而是控制信號。IO設備可以告訴CPU,我這里有數(shù)據(jù)要傳輸給你,但是實際數(shù)據(jù)是CPU從 I/O 設備拉走的,而不是 I/O 設備推給 CPU 的。
不過,DMAC 就很有意思了,它既是一個主設備,又是一個從設備。對于 CPU 來說,它是一個從設備;對于硬盤這樣的 IO 設備來說呢,它又變成了一個主設備。那使用 DMAC進行數(shù)據(jù)傳輸?shù)倪^程究竟是什么樣的呢?下面我們來具體看看。
- 首先是源地址的初始值和傳輸時候的地址增減方式
- 所謂源地址,就是數(shù)據(jù)要從哪里傳輸過來。如果我們要從內存里面寫入數(shù)據(jù)到硬盤上,那么就是要讀取的數(shù)據(jù)在內存里面的地址。如果是從硬盤讀取數(shù)據(jù)到內存,那么就是硬盤的IO接口的地址
- IO的地址可以是一個內存地址,也可以是一個端口地址。而地址的增減就是說,數(shù)據(jù)時從大的地址向小的地址傳輸,還是從小的地址向大的地址傳輸
- 其次就是目標地址(數(shù)據(jù)傳輸?shù)哪康牡?#xff09;初始值和傳輸時候的地址增減方式。
- 第三個自然是要傳輸?shù)臄?shù)據(jù)長度,也就是我們一共要傳輸多少數(shù)據(jù)
所以,整個數(shù)據(jù)傳輸?shù)倪^程中,我們不是通過CPU來搬運數(shù)據(jù),而是由DMAC這個芯片來搬運數(shù)據(jù)。但是CPU在這個過程中也是必不可少的。因為傳輸什么數(shù)據(jù),從哪里傳輸?shù)侥睦?#xff0c;其實還是由CPU來設置的。這也是為什么,DMAC叫做“協(xié)處理器”
最早,計算機里是沒有 DMAC 的,所有數(shù)據(jù)都是由 CPU 來搬運的。隨著對于數(shù)據(jù)傳輸?shù)男枨笤絹碓蕉?#xff0c;先是出現(xiàn)了主板上獨立的 DMAC 控制器。到了今天,各種 I/O 設備越來越
多,數(shù)據(jù)傳輸?shù)男枨笤絹碓綇碗s,使用的場景各不相同。加之顯示器、網(wǎng)卡、硬盤對于數(shù)據(jù)傳輸?shù)男枨蠖疾灰粯?#xff0c;所以各個設備里面都有自己的 DMAC 芯片了。
為什么那么快?一起來看 Kafka 的實現(xiàn)原理
了解了 DMAC 是怎么回事兒,那你可能要問了,這和我們實際進行程序開發(fā)有什么關系呢?有什么 API,我們直接調用一下,就能加速數(shù)據(jù)傳輸,減少 CPU 占用嗎?
過去幾年的大數(shù)據(jù)浪潮里面,還真有一個開源項目很好地利用了 DMA 的數(shù)據(jù)傳輸方式,通過 DMA 的方式實現(xiàn)了非常大的性能提升。這個項目就是Kafka。下面我們就一起來看看它究竟是怎么利用 DMA 的。
- Kafka 是目前實時數(shù)據(jù)傳輸管道的標準解決方案。
- Kafka是一個用來處理實時數(shù)據(jù)的管道,我們常常把它來做一個消息隊列,或者用來收集和落地海量的日志。作為一個處理實時數(shù)據(jù)和日志的管道,瓶頸自然也在IO層面
- Kafka里面常會有兩種常見的海量數(shù)據(jù)傳輸?shù)那闆r,一種是從網(wǎng)絡中接收上游的數(shù)據(jù),然后需要落地到本地磁盤上,確保數(shù)據(jù)不丟失,另一種情況是,從本地磁盤上讀取出來,通過網(wǎng)絡發(fā)送出去。
我們來看一看后一種情況,從磁盤讀數(shù)據(jù)發(fā)送到網(wǎng)絡上去。如果我們自己寫一個簡單的程序,最直觀的辦法,自然是用一個文件讀操作,從磁盤上把數(shù)據(jù)讀到內存里面來,然后再用一個 Socket,把這些數(shù)據(jù)發(fā)送到網(wǎng)絡上去。
File.read(fileDesc, buf, len); Socket.send(socket, buf, len);在這個過程中,數(shù)據(jù)一共發(fā)生了四次傳輸?shù)倪^程,其中兩次是DMA的傳輸,另外兩次是通過CPU控制的傳輸:
- 第一次傳輸,是從硬盤上,讀到操作系統(tǒng)內核的緩沖區(qū)。這個傳輸是通過DMA搬運的
- 第二次傳輸,需要從內核緩沖區(qū)里面的數(shù)據(jù),復制到我們應用分配的內存里面。這個傳輸是通過CPU搬運的
- 第三次傳輸,是要從應用的內存里面,再寫到操作系統(tǒng)的socket的緩沖區(qū)里面去。這個傳輸,還是由CPU搬運的
- 第四次傳輸,需要再從socket緩沖區(qū)里面,寫到網(wǎng)卡的緩沖區(qū)里面去,這個傳輸也是通過DMA搬運的。
這個時候,你可以回過頭看看這個過程。我們只是要“搬運”一份數(shù)據(jù),結果卻整整搬運了四次。而且這里面,從內核的讀緩沖區(qū)傳輸?shù)綉玫膬却胬?#xff0c;再從應用的內存里傳輸?shù)?br /> Socket 的緩沖區(qū)里,其實都是把同一份數(shù)據(jù)在內存里面搬運來搬運去,特別沒有效率。
像 Kafka 這樣的應用場景,其實大部分最終利用到的硬件資源,其實又都是在干這個搬運數(shù)據(jù)的事兒。所以,我們就需要盡可能地減少數(shù)據(jù)搬運的需求。
事實上,Kafka 做的事情就是,把這個數(shù)據(jù)搬運的次數(shù),從上面的四次,變成了兩次,并且只有 DMA 來進行數(shù)據(jù)搬運,而不需要 CPU。
@Override public long transferFrom(FileChannel fileChannel, long position, long count) throws IOExecptionreturn fileChannel.transferTo(position, count, socketChannel); }Kafka的代碼調用了Java NIO庫,具體是FileChannel里面的transsferTo方法。我們的數(shù)據(jù)并沒有讀到中間的應用內存里面,而是直接通過channel,寫入到對應的網(wǎng)絡設備里。并且,對于socket的操作,也不是寫到socket的buffer里面,而是直接根據(jù)描述符寫到網(wǎng)卡的緩沖區(qū)里面。于是,在這個過程之中,我們只進行了兩次數(shù)據(jù)傳輸。
第一次,是通過 DMA,從硬盤直接讀到操作系統(tǒng)內核的讀緩沖區(qū)里面。第二次,則是根據(jù)Socket 的描述符信息,直接從讀緩沖區(qū)里面,寫入到網(wǎng)卡的緩沖區(qū)里面。
這樣,我們同一份數(shù)據(jù)傳輸?shù)拇螖?shù)從四次變成了兩次,并且沒有通過CPU來進行數(shù)據(jù)搬運,所有的數(shù)據(jù)都是通過DMA來進行傳輸?shù)摹?/p>
這這個方法里面,我們沒有在內存層面去“復制”數(shù)據(jù),所以這個方法,也叫做“零拷貝”
在使用了這樣的零拷貝的方法之后呢,我們傳輸同樣數(shù)據(jù)的時間,可以縮減為原來的 1/3,相當于提升了 3 倍的吞吐率。
總結
以上是生活随笔為你收集整理的计算机组成原理:DMA的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 服务器带宽租用常见问题
- 下一篇: String , StringBuild