求逆模
哈喽!今天心血来潮给大家带来了《求逆模》,想必大家应该对Golang都不陌生吧,那么阅读本文就都不会很困难,以下内容主要涉及到,若是你正在学习Golang,千万别错过这篇文章~希望能帮助到你!
我想用模算术计算素数的逆元素。
为了加快速度,我启动了一些 goroutine,尝试在特定范围内查找元素。当第一个找到该元素时,它将其发送到主 goroutine,此时我想终止程序。所以我在主 goroutine 中调用 close ,但我不知道 goroutine 是否会完成执行(我猜不会)。那么就出现了几个问题:
1)这是一种不好的风格吗,我应该有类似 waitgroup 的东西吗?
2)是否有更惯用的方法来进行此计算?
package main
import "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)
}解决方案
这是一种不好的风格吗?我应该有类似 waitgroup 的东西吗?
等待组解决了不同的问题。
一般来说,要成为一个负责任的 go 公民并确保您的代码运行并自行整理,您可能需要执行以下操作的组合:
- 当在其他地方找到计算结果时,向生成的 goroutine 发出信号以停止计算。
- 确保同步进程在返回之前等待 goroutine 停止。如果它们正确响应 #1 中的信号,则这不是强制性的,但如果您不等待,则无法保证它们在父 goroutine 继续之前已终止。
在您的示例程序中,执行此任务然后退出,完全不需要执行任何操作。正如 this comment 所示,程序的 main 方法在找到满意的答案后终止,此时程序将结束,所有 goroutine 将立即终止,操作系统将清理所有消耗的资源。等待 goroutine 停止是不必要的。
但是,如果您将此代码打包到一个库中,或者它成为长时间运行的“逆素数计算”服务的一部分,则需要整理您生成的 goroutine 以避免不必要地浪费周期。此外,一般来说,您可能会遇到其他情况,其中 goroutine 存储状态、保存外部资源的句柄或保存内部对象的句柄,如果不正确清理,这些对象可能会泄漏 – 最好正确关闭这些内容。
传达停止工作的要求
有几种方法可以传达这一点。我并不认为这是一份详尽的清单! (请在评论中建议其他通用方法或建议对帖子进行编辑。)
使用特殊通道
通过关闭为此目的保留的特殊“关闭”通道来向子 goroutine 发出信号。这利用了通道 axiom:
来自关闭通道的接收立即返回零值
从关闭通道接收到消息后,goroutine 应立即安排整理任何本地状态并从函数返回。您之前的问题有实现此功能的示例代码;该模式的一个版本是:
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)
}
在这种情况下,关闭逻辑被浪费了,因为 main() 方法将在调用 close 后立即返回。这将与 goroutine 的关闭竞争,但我们应该假设它不会正确执行其整理行为。第 2 点提出了解决此问题的方法。
使用上下文
context 包提供了创建可取消上下文的选项。取消时,上下文的 done() 方法公开的通道将被关闭,这表示从 goroutine 返回的时间。
这种方法与之前的方法大致相同,除了更简洁的封装以及可以将上下文传递给 goroutine 中的下游调用以在需要时取消嵌套调用之外。示例:
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()
}
这与其他情况具有相同的错误,即 main 方法在返回之前不会等待子 goroutine 退出。
等待(或“加入”)子 goroutine 停止
上面示例中关闭关闭通道或关闭上下文的代码不会等待子 goroutine 停止工作后再继续。在某些情况下,这可能是可以接受的,而在其他情况下,您可能需要保证 goroutine 在继续之前已停止。
sync.waitgroup可以用来实现这个需求。 documentation很全面。等待组是一个计数器,应该在启动 goroutine 时使用其 add 方法递增,并在 goroutine 完成时使用其 done 方法递减。代码可以通过调用其 wait 方法来等待计数器返回到零,该方法将阻塞,直到条件为真。对 add 的所有调用都必须在对 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()
}
是否有更惯用的方法来进行此计算?
通过按照您定义的方式使用 goroutine,该算法当然可以并行化。由于工作受 cpu 限制,因此限制 goroutine 对可用 cpu 的数量是有意义的(在机器上没有其他工作的情况下),以便从可用的计算资源中受益。
请参阅 peterSO's answer 以获取错误修复。
您实际上不需要循环来计算它。
如果您使用 GCD function(标准库的一部分),您将得到返回的数字 x 和 y,如下所示:
x*p+y*base=1
这意味着 x 是您想要的答案(因为 x*p = 1 模基数):
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)
}今天关于《求逆模》的内容就介绍到这里了,是不是学起来一目了然!想要了解更多关于的内容请关注golang学习网公众号!
在CentOS 7.9上找不到 /usr/local/go/bin 这个目录
- 上一篇
- 在CentOS 7.9上找不到 /usr/local/go/bin 这个目录
- 下一篇
- PHP SDK的定义和作用是什么?
-
- Golang · Go问答 | 1天前 | 并发 · go · 初始化 · Go 初始化错误 sync.OnceValue 并发排障
- OnceValue 初始化错误缓存后的恢复策略
- 500浏览 收藏
-
- Golang · Go问答 | 1天前 | 并发 · go · Go sync.RWMutex 并发排障 读锁升级
- RWMutex 写锁升级导致阻塞时的改造方案
- 395浏览 收藏
-
- Golang · Go问答 | 1天前 | 并发 · go · Go sync.Mutex 指针接收者 copylocks 并发排障
- sync.Mutex 复制后出现异常解锁的结构体设计
- 448浏览 收藏
-
- Golang · Go问答 | 1天前 | 并发 · go · Go wait add sync.WaitGroup Done 并发收尾 WaitGroup.Go
- WaitGroup Go 方法调用顺序的并发收尾
- 455浏览 收藏
-
- Golang · Go问答 | 1天前 | 并发 · go · Context · Go context Context.Value WithValue
- context.WithValue 键类型冲突导致字段覆盖的规避
- 277浏览 收藏
-
- Golang · Go问答 | 1天前 |
- context.Cause 区分主动取消与超时取消
- 485浏览 收藏
-
- Golang · Go问答 | 1天前 | go ·
- context.AfterFunc 回调未执行时的取消时序
- 342浏览 收藏
-
- Golang · Go问答 | 1天前 |
- HTTP Trailer 读取为空时的响应头声明顺序
- 448浏览 收藏
-
- Golang · Go问答 | 1天前 |
- HTTP 服务器读取请求体超时的连接处理
- 290浏览 收藏
-
- Golang · Go问答 | 1天前 |
- net/http 客户端关闭连接后请求体重用的限制
- 497浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 432次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 508次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 524次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 464次使用
-
- MMBench
- MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
- 294次使用
-
- 用Nginx反向代理部署go写的网站。
- 2023-01-17 502浏览
-
- GoLand调式动态执行代码
- 2023-01-13 502浏览
-
- Go crypto/rand.Text 的长度为什么不是固定字符数
- 2026-10-04 501浏览
-
- Go strings.ToValidUTF8 清洗日志内容的边界
- 2026-10-03 501浏览
-
- Go tls.GetCertificate 为什么收不到空 ServerName 请求
- 2026-09-27 501浏览

