2017-08-16 181 views
-2

爲了純粹的教育目的,我創建了一個base58包。它將編碼/使用bitcoin base58 symbol chart解碼uint64,例如:如何同時迭代int範圍

b58 := Encode(100) // return 2j 

num := Decode("2j") // return 100 

在創建我帶着this的第一次測試:

func TestEncode(t *testing.T) { 
    var i uint64 
    for i = 0; i <= (1<<64 - 1); i++ { 
     b58 := Encode(i) 
     num := Decode(b58) 
     if num != i { 
      t.Fatalf("Expecting %d for %s", i, b58) 
     } 
    } 
} 

這種「幼稚」的實施,會嘗試把所有的範圍從uint64(從0到18,446,744,073,709,551,615)到base58,然後返回到uint64,但花費太多時間。

爲了更好地理解go如何處理併發性,我想知道如何使用通道或goroutines並以最有效的方式在整個uint64範圍內執行迭代?

數據是否可以通過塊並行處理,如果是的話如何實現?

在此先感謝。

UPDATE

像由@Adrien在回答提到,一個方法是使用t.Parallel()但只是測試包時適用,在任何情況下,通過實現它,我發現這是明顯慢了,它並行運行,但沒有速度增益。

我明白,拼盡了全力uint64可能需要幾年時間,但我想要的東西找到/現在怎麼可能一個通道或夠程,可能有助於加快這一進程(小範圍1<<16測試)可能是通過使用這樣的事情https://play.golang.org/p/9U22NfrXeq只是一個例子。

問題不在於如何測試軟件包是關於什麼算法,可以使用技術通過使用併發來更快地進行迭代。

+2

請注意,此測試也不能證明您的實現實際上是正確的;只有解碼/編碼匹配。如果他們都以同樣的方式錯誤,測試將通過。您需要對照規範值進行測試以證明正確性。 – Adrian

+5

如果您的編碼/解碼能夠在一個CPU上每秒完成10億次轉換(這非常樂觀),您需要60個CPU才能在10年內完成此任務。這是假設從goroutines和渠道沒有開銷。 –

+0

@PaulHankin你是完全正確的,但我的想法是試圖理解如何解決這個問題時,通過使用頻道goroutines處理素數,儘管需要幾年,我想了解更多關於如何優化。 – nbari

回答

0

我想出了這個解決方案:

package main 

import (
    "fmt" 
    "time" 

    "github.com/nbari/base58" 
) 

func encode(i uint64) { 
    x := base58.Encode(i) 
    fmt.Printf("%d = %s\n", i, x) 
    time.Sleep(time.Second) 
} 

func main() { 
    concurrency := 4 
    sem := make(chan struct{}, concurrency) 
    for i, val := uint64(0), uint64(1<<16); i <= val; i++ { 
     sem <- struct{}{} 
     go func(i uint64) { 
      defer func() { <-sem }() 
      encode(i) 
     }(i) 
    } 
    for i := 0; i < cap(sem); i++ { 
     sem <- struct{}{} 
    } 
} 

基本上,啓動4名工人,並調用編碼功能,爲了更多地注意/理解這種行爲,添加睡眠以便數據可以以大塊4打印。

另外,這些答案幫助d我更好地瞭解併發理解:https://stackoverflow.com/a/18405460/1135424

如果有更好的方法,請讓我知道。

1

此功能內置到圍棋testing包,在T.Parallel形式:

func TestEncode(t *testing.T) { 
    var i uint64 
    for i = 0; i <= (1<<64 - 1); i++ { 
     t.Run(fmt.Sprintf("%d",i), func(t *testing.T) { 
      j := i   // Copy to local var - important 
      t.Parallel()  // Mark test as parallelizable 
      b58 := Encode(j) 
      num := Decode(b58) 
      if num != j { 
       t.Fatalf("Expecting %d for %s", j, b58) 
      } 
     }) 
    } 
} 
+0

感謝您指出T.Parrallel,但是您可以請修復示例以使其工作,如果我正確't.Run()'缺少''''第二個Itoa似乎不適用於'uint64':'不能在strconv.Itoa參數中使用i(type uint64)作爲int類型參數' – nbari

+0

已更正的代碼示例,但似乎您有這個想法。 – Adrian

+0

任何想法爲什麼當並行運行需要更多的時間(比較慢),而不是在t.Parallel()中運行? – nbari