如何同时迭代int范围

时间:2017-08-16 19:29:29

标签: go concurrency

出于纯粹的教育目的,我创建了一个base58包。它将使用bitcoin base58 symbol chartuint64进行编码/解码,例如:

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范围内执行迭代?

数据是否可以通过块并行处理,如果是,如何完成此操作?

提前致谢。

更新

@Adrien的答案中提到,单向是使用t.Parallel(),但这仅适用于测试包时,无论如何,通过实现它我发现它明显更慢,它并行运行,但没有速度增益。

据我所知,完整uint64可能需要数年时间,但我想要找到/现在是一个频道或goroutine可能有助于加快这一过程(使用小范围进行测试1<<16 )可能通过使用类似https://play.golang.org/p/9U22NfrXeq之类的东西作为例子。

问题不是关于如何测试包是关于什么算法,技术可以用于通过使用并发更快地迭代。

2 个答案:

答案 0 :(得分:1)

此功能内置于Go 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)
            }
        })
    }
}

答案 1 :(得分: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个worker并调用encode函数,注意/了解更多这种行为,添加一个sleep,以便数据可以打印成4个块。

此外,这些答案帮助我更好地理解并发理解:https://stackoverflow.com/a/18405460/1135424

如果有更好的方法,请告诉我。