Channels Concurrency Work-Around

记录了一些channels常见的场景,以及自己的一些感受: 使用通道进行异步和并发编程是简单和惬意的; 通道同步技术比被很多其它语言采用的其它同步方案(比如角色模型和async/await模式)有着更多的应用场景和更多的使用变种。 通道作为同步手段,并非在任何情况下都是最佳的同步技术,本文也会补充原子操作和sync包内其他的技术作为参考。 将通道用做future/promise 很多其它流行语言支持future/promise来实现异步(并发)编程。 Future/promise常常用在请求/回应场合。 返回单向接收通道做为函数返回结果 在下面这个例子中,sumSquares函数调用的两个实参请求并发进行。 每个通道读取操作将阻塞到请求返回结果为止。 两个实参总共需要大约3秒钟(而不是6秒钟)准备完毕(以较慢的一个为准)。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 package main import ( "time" "math/rand" "fmt" ) func longTimeRequest() <-chan int32 { r := make(chan int32) go func() { time.Sleep(time.Second * 3) // 模拟一个工作负载 r <- rand.Int31n(100) }() return r } func sumSquares(a, b int32) int32 { return a*a + b*b } func main() { rand.Seed(time.Now().UnixNano()) a, b := longTimeRequest(), longTimeRequest() fmt.Println(sumSquares(<-a, <-b)) } 将单向发送通道类型用做函数实参 和上例一样,在下面这个例子中,sumSquares函数调用的两个实参的请求也是并发进行的。 和上例不同的是longTimeRequest函数接收一个单向发送通道类型参数而不是返回一个单向接收通道结果。 ...

December 22, 2020 · 14 min · 2852 words · Me

Black Magic

阅读到的一些方便、有趣的技巧或者ideas的随手记录,后续考虑对相关话题专门开坑 一行代码画出专业的论文图 SciencePlots 计算机专业向来不缺少专业的绘图软件,从Excel到PPT,从最近沸沸扬扬的Matlab到Matplotlib、pyplot、ggplot,乃至其他更为专业的软件,着实丰富了我们的画图生活。 但是,这些软件或工具的背后,常常需要我们付出更多的努力:调色、统一格式、展示要高大上,等等。 现在,一款开源的软件工具包问世了:SciencePlots。它让你用一行代码画出天然高端且美观的论文图。 SciencePlots是一个依附于Matplotlib的扩展包,可以通过pip一键安装: pip install SciencePlots 然后我们在画图时,只需要一句with.plt.style.context(['science']):,就可以画出非常美观且专业的图: 你还可以加一个选项with.plt.style.context(['science','ieee']):,就能画出IEEE格式的图: 甚至是超美的散点图: 还有很多自定义的图像风格,保证节约我们的画图时间 这个包默认会调用latex来画图,如果不想用latex(也不是完全需要),可以在context里写一个属性’nolatex’即可。不然如果没有安装latex或latex路径配置有问题,则会报错。

December 20, 2020 · 1 min · 15 words · Me

书单记录

这个post为记录目前正在阅读与研究的section Go语言设计 Go语言设计与实现 Go Under The Hood 这两本在写作目的和内容规划都是一致的,不过第二个原本不再维护内容,作者开了下面的新的项目,把撰写原本而积累的与Go相关的资源进行了重新的整理。 Go设计历史 pprof对服务端性能影响的研究 考虑一些极端场景,比如极度追求性能,压榨系统资源以及技术栈必须是Go的业务场景下,是否能自己构建Reactor网络模型 GRPC框架对服务侧性能的影响 Russ Cox正则表达式系列 You should not be permitted to write production code if you do not have an journeyman license in regular expressions or floating point math. – Rob Pike Regular Expression Matching Can Be Simple And Fast 编译器词法分析:正则语言和正则表达式 Go内存原理与调度模型 正在整理专栏 Bound Checking Elimination Crafting Interpreter 时常看PL和Compiler的基础 crafting interpreters Kosaraju’s Algorithm 看William Lin的coding interview觉得用来处理树和图很好,算法4里也有 Heilmeier问题系列 思考某篇paper的选题 What are you trying to do? Articulate your objectives using absolutely no jargon. How is it done today, and what are the limits of current practice? Who cares? [Support other’s research? Shape research landscape? Power applications in industry?] What’s new in your approach and why do you think it will be successful? If you’re successful, what difference will it make? [e.g. Contributions in theory/modeling? Improve accuracy by 5% on dataset A, B, C…?] What are the risks and the payoffs? [Further, how would you mitigate the risks? If your proposed method does not work, what could be alternative design? These can end up as discussions such as ablation studies in your paper.] How much will it cost? [e.g. How many GPUs do your experiments require? How long is each training process? How about data storage?] How long will it take? [How many hours are you going to work on this per week? When is the submission DDL? Can you make it?] What are the midterm and final “exams” to check for success?

December 19, 2020 · 2 min · 239 words · Me

Golang TDD

Preface 本文整理golang编码的单元测试常用示例,以及TDD的简要流程。 单元测试基础 单元测试文件以_test.go结尾,需要记住以下原则: 文件名必须是_test.go结尾的,这样在执行go test的时候才会执行到相应的代码 你必须import testing这个包 所有的测试用例函数必须是Test开头 测试用例会按照源代码中写的顺序依次执行 测试函数TestXxx()的参数是testing.T,我们可以使用该类型来记录错误或者是测试状态 测试格式:func TestXxx (t *testing.T),Xxx部分可以为任意的字母数字的组合,但是首字母不能是小写字母[a-z],例如Testintdiv是错误的函数名。 函数中通过调用testing.T的Error, Errorf, FailNow, Fatal, FatalIf方法,说明测试不通过,调用Log方法用来记录测试的信息。 Table-Driven-Testing 测试讲究 case 覆盖,当我们要覆盖更多 case 时,显然通过修改代码的方式很笨拙。这时我们可以采用 Table-Driven 的方式写测试,标准库中有很多测试是使用这种方式写的。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 func TestFib(t *testing.T) { var fibTests = []struct { in int // input expected int // expected result }{ {1, 1}, {2, 1}, {3, 2}, {4, 3}, {5, 5}, {6, 8}, {7, 13}, } for _, tt := range fibTests { actual := Fib(tt.in) if actual != tt.expected { t.Errorf("Fib(%d) = %d; expected %d", tt.in, actual, tt.expected) } } } 由于我们使用的是 t.Errorf,即使其中某个 case 失败,也不会终止测试执行。 ...

December 19, 2020 · 17 min · 3480 words · Me

Golang并发调度

性能提升不会凭空出现,它总是伴随着代码复杂度的上升。 The performance improvement does not materialize from the air, it comes with code complexity increase. – Dmitry Vyukov Go 语言的调度器我认为应该是整个运行时最有趣的组件了。对于Go本身,它的设计和实现直接牵动了Go运行时的其他组件,也是和用户态代码直接打交道的部分;对于Go用户而言,调度器将其极为复杂的运行机制隐藏在了简单的关键字go下。为了保证高性能,调度器必须有效得利用计算的并行性和局部性原理;为了保证用户态的简洁,调度器必须高效得对调度用户态不可见的网络轮训器、垃圾回收器进行调度;为了保证代码执行的正确性,必须严格实现用户态代码的内存顺序等。总而言之,调度器的设计直接决定了Go运行时源码的表现形式。 设计原理 数据结构: MPG 调度器启动 创建Goroutine 调度循环 触发调度 线程管理 总结

December 17, 2020 · 1 min · 30 words · Me