第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問題,去搜搜看,總會(huì)有你想問的

計(jì)算模逆、

計(jì)算模逆、

Go
哆啦的時(shí)光機(jī) 2023-03-29 16:15:12
我想計(jì)算模運(yùn)算中素?cái)?shù)的逆元素。為了加快速度,我啟動(dòng)了幾個(gè) goroutine,它們?cè)噲D在一定范圍內(nèi)找到元素。當(dāng)?shù)谝粋€(gè)找到元素時(shí),它將它發(fā)送到主 goroutine,此時(shí)我想終止程序。所以我調(diào)用close了主 goroutine,但我不知道 goroutines 是否會(huì)完成它們的執(zhí)行(我猜不會(huì))。于是出現(xiàn)了幾個(gè)問題:1)這是一種糟糕的風(fēng)格,我應(yīng)該有類似的東西嗎WaitGroup?2)是否有更慣用的方法來(lái)進(jìn)行此計(jì)算?package mainimport "fmt"const (    Procs = 8    P     = 1000099    Base  = 1<<31 - 1)func compute(start, end uint64, finished chan struct{}, output chan uint64) {    for i := start; i < end; i++ {        select {        case <-finished:            return        default:            break        }        if i*P%Base == 1 {            output <- i        }    }}func main() {    finished := make(chan struct{})    output := make(chan uint64)    for i := uint64(0); i < Procs; i++ {        start := i * (Base / Procs)        end := (i + 1) * (Base / Procs)        go compute(start, end, finished, output)    }    fmt.Println(<-output)    close(finished)}
查看完整描述

2 回答

?
瀟湘沐

TA貢獻(xiàn)1816條經(jīng)驗(yàn) 獲得超6個(gè)贊

有沒有更慣用的方法來(lái)進(jìn)行這種計(jì)算?

您實(shí)際上不需要循環(huán)來(lái)計(jì)算它。

如果你使用GCD 函數(shù)(標(biāo)準(zhǔn)庫(kù)的一部分),你會(huì)得到返回的數(shù)字 x 和 y,這樣:

x*P+y*Base=1

這意味著 x 是您想要的答案(因?yàn)?x*P = 1 modulo Base):

package main


import (

? ? "fmt"

? ? "math/big"

)


const (

? ? P? ? = 1000099

? ? Base = 1<<31 - 1

)


func main() {

? ? bigP := big.NewInt(P)

? ? bigBase := big.NewInt(Base)

? ? // Compute inverse of bigP modulo bigBase

? ? bigGcd := big.NewInt(0)

? ? bigX := big.NewInt(0)

? ? bigGcd.GCD(bigX,nil,bigP,bigBase)

? ? // x*bigP+y*bigBase=1?

? ? // => x*bigP = 1 modulo bigBase

? ? fmt.Println(bigX)

}


查看完整回答
反對(duì) 回復(fù) 2023-03-29
?
蝴蝶不菲

TA貢獻(xiàn)1810條經(jīng)驗(yàn) 獲得超4個(gè)贊

這是一種糟糕的風(fēng)格,我應(yīng)該有類似的東西嗎WaitGroup?

等待組解決了不同的問題。

一般來(lái)說(shuō),要在這里成為一個(gè)負(fù)責(zé)任的 go 公民并確保您的代碼運(yùn)行并在其背后進(jìn)行整理,您可能需要結(jié)合執(zhí)行以下操作:

  1. 當(dāng)在別處找到計(jì)算結(jié)果時(shí),向生成的 goroutines 發(fā)出停止計(jì)算的信號(hào)。

  2. 確保同步進(jìn)程在返回之前等待 goroutines 停止。如果它們正確響應(yīng)#1 中的信號(hào),這不是強(qiáng)制性的,但如果您不等待,則無(wú)法保證它們?cè)诟?goroutine 繼續(xù)之前已終止。

在執(zhí)行此任務(wù)然后退出的示例程序中,絕對(duì)不需要執(zhí)行任何操作。正如這條評(píng)論所指出的,您的程序的main方法在找到滿意的答案后終止,此時(shí)程序?qū)⒔Y(jié)束,所有 goroutine 將立即終止,并且操作系統(tǒng)將整理所有消耗的資源。等待 goroutines 停止是不必要的。

但是,如果您將這段代碼打包到一個(gè)庫(kù)中,或者它成為長(zhǎng)期運(yùn)行的“反素?cái)?shù)計(jì)算”服務(wù)的一部分,那么最好整理您生成的 goroutine 以避免不必要地浪費(fèi)周期。此外,一般來(lái)說(shuō),您可能還有其他場(chǎng)景,其中 goroutines 存儲(chǔ)狀態(tài)、持有外部資源的句柄或持有內(nèi)部對(duì)象的句柄,如果沒有妥善整理,您就有泄漏的風(fēng)險(xiǎn)——最好適當(dāng)?shù)仃P(guān)閉這些。


傳達(dá)停止工作的要求

有幾種方法可以傳達(dá)這一點(diǎn)。我不認(rèn)為這是一個(gè)詳盡的清單!(請(qǐng)?jiān)谠u(píng)論中或通過(guò)對(duì)帖子提出編輯建議來(lái)建議其他通用方法。)

使用特殊渠道

通過(guò)關(guān)閉為此目的保留的特殊“關(guān)閉”通道向子 goroutine 發(fā)出信號(hào)。這利用了通道公理

來(lái)自關(guān)閉通道的接收立即返回零值

從關(guān)閉通道接收后,goroutine 應(yīng)立即安排整理任何本地狀態(tài)并從函數(shù)返回。您之前的問題有實(shí)現(xiàn)此功能的示例代碼;該模式的一個(gè)版本是:

func myGoRoutine(shutdownChan <-chan struct{}) {

    select {

    case <-shutdownChan:

        // tidy up behaviour goes here

        return

    // You may choose to listen on other channels here to implement

    // the primary behaviour of the goroutine.

    }

}


func main() {

    shutdownChan := make(chan struct{})

    go myGoRoutine(shutdownChan)


    // some time later

    close(shutdownChan)

}

在這種情況下,關(guān)閉邏輯被浪費(fèi)了,因?yàn)樵搈ain()方法將在調(diào)用后立即返回close。這將與 goroutine 的關(guān)閉競(jìng)爭(zhēng),但我們應(yīng)該假設(shè)它不會(huì)正確執(zhí)行其整理行為。第 2 點(diǎn)解決了解決此問題的方法。


使用上下文

該context包提供了創(chuàng)建可以取消的上下文的選項(xiàng)。取消時(shí),上下文Done()方法公開的通道將關(guān)閉,這標(biāo)志著從 goroutine 返回的時(shí)間。


這種方法與之前的方法大致相同,除了更簡(jiǎn)潔的封裝和上下文的可用性以傳遞給 goroutine 中的下游調(diào)用以在需要時(shí)取消嵌套調(diào)用。例子:


func myGoRoutine(ctx context.Context) {

    select {

    case <-ctx.Done():

        // tidy up behaviour goes here

        return

    // Put real behaviour for the goroutine here.

    }

}


func main() {

    // Get a context (or use an existing one if you are provided with one

    // outside a `main` method:

    ctx := context.Background()


    // Create a derived context with a cancellation method

    ctx, cancel := context.WithCancel(ctx)


    go myGoRoutine(ctx)


    // Later, when ready to quit

    cancel()

}

這與另一種情況有相同的錯(cuò)誤,因?yàn)樵搈ain方法不會(huì)等待子 goroutines 在返回之前退出。


等待(或“加入”)子協(xié)程停止

上面示例中關(guān)閉關(guān)閉通道或關(guān)閉上下文的代碼不會(huì)等待子 goroutine 停止工作再繼續(xù)。這在某些情況下可能是可以接受的,而在其他情況下,您可能需要保證 goroutines 在繼續(xù)之前已經(jīng)停止。


sync.WaitGroup可以用來(lái)實(shí)現(xiàn)這個(gè)要求。文檔很全面。等待組是一個(gè)計(jì)數(shù)器,它應(yīng)該Add在啟動(dòng) goroutine 時(shí)使用它的方法遞增,并Done在 goroutine 完成時(shí)使用它的方法遞減。代碼可以通過(guò)調(diào)用其方法等待計(jì)數(shù)器歸零Wait,該方法會(huì)阻塞直到條件為真。對(duì) 的所有調(diào)用都Add必須在對(duì) 的調(diào)用之前發(fā)生Wait。


示例代碼:


func main() {

    var wg sync.WaitGroup


    // Increment the WaitGroup with the number of goroutines we're

    // spawning.

    wg.Add(1)


    // It is common to wrap a goroutine in a function which performs

    // the decrement on the WaitGroup once the called function returns

    // to avoid passing references of this control logic to the

    // downstream consumer.

    go func() {

        // TODO: implement a method to communicate shutdown.

        callMyFunction()

        wg.Done()

    }()


    // Indicate shutdown, e.g. by closing a channel or cancelling a

    // context.


    // Wait for goroutines to stop

    wg.Wait()

}

有沒有更慣用的方法來(lái)進(jìn)行這種計(jì)算?


通過(guò)以您定義的方式使用 goroutines,該算法當(dāng)然可以并行化。由于工作受 CPU 限制,goroutines 對(duì)可用 CPU 數(shù)量的限制是有意義的(在機(jī)器上沒有其他工作的情況下)以從可用計(jì)算資源中獲益。


查看完整回答
反對(duì) 回復(fù) 2023-03-29
  • 2 回答
  • 0 關(guān)注
  • 133 瀏覽
慕課專欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)