使用 GPU 進行比特幣挖礦計算,具體是如何工作的?

GPU的VLIW5,VLIW4的架構對挖礦有影響嗎?


要解釋 GPU 的體系結構對於挖礦程序性能的影響,需要從演算法本身入手。但簡單來說我們可以認為 GPU 挖礦的性能只與兩點有關:1)GPU 整數運算單元的數量。2)程序在目標體系結構上的利用率。因此直接回答題主的問題:AMD 的 VLIW5 和 VLIW4 在整數運算單元數量一致的情況下,誰的利用率高,誰的挖礦性能就越高。

挖礦程序的實質是計算 Hash,即大量的整數運算。後期的幣種,如 LiteCoin 所使用的 Scrypt 演算法還引入了大量相互依賴的、隨機的訪存指令,以弱化礦機(ASIC/FPGA)相較於 GPU 在整數運算性能上的優勢。

以 bfgminer 中 Scrypt 演算法的 OpenCL 實現為例,

首先是 Kernel 的主體結構,大致邏輯是並行的計算多個 Hash 值,並保存於顯存:

void scrypt_core(uint4 X[8], __global uint4*restrict lookup)
{
shittify(X);
const uint zSIZE = 8;
const uint ySIZE = (1024/LOOKUP_GAP+(1024%LOOKUP_GAP&>0));
const uint xSIZE = CONCURRENT_THREADS;
uint x = get_global_id(0)%xSIZE;

for(uint y=0; y&<1024/LOOKUP_GAP; ++y) { #pragma unroll for(uint z=0; z&

Scrypt 演算法的核心是 Salsa20/8,通過此 Hash 演算法產生隨機的訪存。當 Footprint 足夠大時,還會在 GPU 的 L2 級別、甚至 TLB 級別出現大量的緩存失效,從而產生更多的 DRAM 訪問。

void salsa(uint4 B[8])
{
uint4 w[4];

#pragma unroll
for(uint i=0; i&<4; ++i) w[i] = (B[i]^=B[i+4]); #pragma unroll for(uint i=0; i&<4; ++i) { w[0] ^= rotl(w[3] +w[2] , 7U); w[1] ^= rotl(w[0] +w[3] , 9U); w[2] ^= rotl(w[1] +w[0] ,13U); w[3] ^= rotl(w[2] +w[1] ,18U); w[2] ^= rotl(w[3].wxyz+w[0].zwxy, 7U); w[1] ^= rotl(w[2].wxyz+w[3].zwxy, 9U); w[0] ^= rotl(w[1].wxyz+w[2].zwxy,13U); w[3] ^= rotl(w[0].wxyz+w[1].zwxy,18U); } #pragma unroll for(uint i=0; i&<4; ++i) w[i] = (B[i+4]^=(B[i]+=w[i])); #pragma unroll for(uint i=0; i&<4; ++i) { w[0] ^= rotl(w[3] +w[2] , 7U); w[1] ^= rotl(w[0] +w[3] , 9U); w[2] ^= rotl(w[1] +w[0] ,13U); w[3] ^= rotl(w[2] +w[1] ,18U); w[2] ^= rotl(w[3].wxyz+w[0].zwxy, 7U); w[1] ^= rotl(w[2].wxyz+w[3].zwxy, 9U); w[0] ^= rotl(w[1].wxyz+w[2].zwxy,13U); w[3] ^= rotl(w[0].wxyz+w[1].zwxy,18U); } #pragma unroll for(uint i=0; i&<4; ++i) B[i+4] += w[i]; }

理想的情況下 Scrypt 演算法的瓶頸會出現在內存帶寬上,而這也是 ASIC/FPGA 無法規避的問題,因此理論上 GPU 與礦機的性能基本一致。當然了,實際情況下 GPU 的訪存帶寬受限於種種條件(如整數運算單元不足,寄存器數量有限等),往往是無法將訪存帶寬利用滿的。

再回到題主的問題,從 GPU 體系結構的角度來看,從早期的 VLIW、Fermi 到現在的 GCN 、Maxwell,主要的改進方向就是儘可能的挖掘計算單元和訪存單元的利用率。也就是說,越新的架構在同樣的晶元面積下性能也會越好。同樣的,新架構帶來的高利用率還可以降低功耗,帶來更高的能耗比(Perf/Watt)。

所以買新卡總是不會錯的 ^_^


第一名的答主雖然貼了代碼但是回到原題關於比特幣和GPU如何計算的問題上,
我把之前整理的一些關於比特幣和GPU以及礦機的筆記貼一貼,拋磚引玉。

所以挖礦到底特么的是在幹嘛?
挖礦就是用計算的方法,把已有的10分鐘內的所有交易作為一個輸入,加上一個隨機數(這個隨機數是需要不停試錯的,這就是挖礦機做的事情),當10分鐘內所有交易記錄加上你的這個隨機數計算出一個SHA256的hash。這個hash要滿足的條件是,它的最高20bit為全零。這是為什麼?因為:

hashcash 機制大致描述如下(Hashcash.org):
如果希望判定一個人提供的的信息是本著正常使用,具備一定價值的。那麼我們傾向認為提供這個信息的人,願意為此付出一定工作量來證明他的誠實。假如有一種機制,能夠容易的證明提供信息的人為此付出了一定工作量,那麼此信息是可以接受,並被認為合理的。
比如,我收郵件的時候,做了一個規定:「把郵件內容數據,加入一個隨機數,求一個sha256散列數值。這個散列值一共256bit 。前20bit 必須都為0」.
這樣,要給我發信的人,就必須反覆嘗試一個隨機數,以保證郵件內容數據加上這個隨機數,能夠產生sha256 的結果------前20bit 都是0.(這個計算過程本身毫無意義)
如何產生出指定要求的整數?完全靠運氣和CPU 運算時間。這就是一個工作量。工作本身毫無意義。但是如果誰願意付出這個工作量,就意味著他給我的郵件多半是有意義的。這就叫「工作量證明」。也就是意味著這個人很有可能是誠實的。這裡把郵件換成Block也是等效的。
這個機制被廣泛用於防止垃圾郵件等。因為群發垃圾郵件的人,不可能有那麼多時間去給每個人算一個毫無意義的數字,浪費時間,降低發垃圾郵件的效率。
挖礦的目的是確認交易。尋找隨機數的過程是為了保證每一個挖礦節點不會往外發送垃圾block。發送的BlockId是這個Block的Hash,它必然是首20bit為0的。

那麼問題來了: 既然CPU可以算,為什麼大家用GPU挖礦? 那是因為顯然後者效率更高,投入產出比更合理。 比特幣採用的演算法偽碼如下:

function mine()
{
while(true)
{
longestChain = getLongestValidChain()

-- A number that changes every time, so that you don"t waste time
-- trying to calculate a valid blockHash with the same input.
nonce = getNewNonce()

currentTXs = getUnconfirmedTransactionsFromNetwork()

newBlock = getNewBlock(longestChain, currentTX, nonce)

-- http://en.wikipedia.org/wiki/SHA-2
-- and this is what all the "mining machines" are doing.
blockHash = sha256(newBlock)

if((blockHash0xFFFF_F000_0000_..._000) == 256"b0) // blockHash (256bit) has 20bit MSB as 0, then confirm this block as valid
{
broadcast(newBlock)
-- Now the height the block chain is incremented by 1
-- (if the new block is accepted by other peers),
-- and all the TXs in the new block are "confirmed"
}
}
}
////////////////////////////////////////////////////////////////
function sendBTC(amount)
{
sourceTXs = pickConfirmedTransactionsToBeSpent(amount)
tx = generateTX(sourceTXs, targetAddrs, amount, fee)
signedTx = sign(tx, privateKeysOfAllInputAddress)
broadcast(signedTx)
}
////////////////////////////////////////////////////////////////

可以預見的是對於比特幣的Hash計算而言,它幾乎都是獨立並發的整數計算,GPU簡直就是為了這個而設計生產出來的。相比較CPU可憐的2-8線程和長度驚人的控制判斷和調度分支,GPU可以輕易的進行數百個線程的整數計算並發(無需任何判斷的無腦暴力破解乃是A卡的強項)。
OpenCL可以利用GPU在片的大量unified shader都可以用來作為整數計算的資源。而A卡的shader(流處理器)資源又是N的數倍(同等級別的卡)。
而為什麼普遍使用AMD的顯卡計算效率比較高?
有數據表明同樣是主流的顯卡
AMD HD 7990 | 速率 1073.5 MHash/S
而NV的 GTX TITAN | 速率 302.4 MHash/S
還有一種說法是:

比特幣挖掘器採用的是SHA-256,這是由美國國家安全局發明的一種安全散列函數,一般用於密碼加密與解密。這種演算法會進行大量32位整數循環右移運算,這個操作在AMD GPU那裡可以通過單一硬體指令實現,而在NVIDIA GPU那裡需要三次硬體指令來模擬(2移+1加),僅這一條就為AMD帶來額外的1.7倍運算效率優勢(大約1900指令來執行SHA-256壓縮操作,而不是NVIDIA的大約3250指令)
引自貼吧一片科普文—


推薦閱讀:

如何看待 IBM 宣布成功研製 50 量子比特量子計算機原型機?

TAG:圖形處理器(GPU) | GPU 通用計算 | 比特幣 (Bitcoin) | 密碼學 |