我正在尝试了解 go-routines 的工作原理。这是一些代码:
//parallelSum.go
func sum(a []int, c chan<- int, func_id string) {
sum := 0
for _, n := range a {
sum += n
}
log.Printf("func_id %v is DONE!", func_id)
c <- sum
}
func main() {
ELEM_COUNT := 10000000
test_arr := make([]int, ELEM_COUNT)
for i := 0; i < ELEM_COUNT; i++ {
test_arr[i] = i * 2
}
c1 := make(chan int)
c2 := make(chan int)
go sum(test_arr[:len(test_arr)/2], c1, "1")
go sum(test_arr[len(test_arr)/2:], c2, "2")
x := <-c1
y := <-c2
//x, y := <-c, <-c
log.Printf("x= %v, y = %v, sum = %v", x, y, x+y)
}
以上程序运行良好并返回输出。我有同一个程序的迭代版本:
//iterSum.go
func sumIter(a []int, c *int, func_id string) {
sum := 0
log.Printf("entered the func %s", func_id)
for _, n := range a {
sum += n
}
log.Printf("func_id %v is DONE!", func_id)
*c = sum
}
func main() {
*/
ELEM_COUNT := 10000000
test_arr := make([]int, ELEM_COUNT)
for i := 0; i < ELEM_COUNT; i++ {
test_arr[i] = i * 2
}
var (
i1 int
i2 int
)
sumIter(test_arr[:len(test_arr)/2], &i1, "1")
sumIter(test_arr[len(test_arr)/2:], &i2, "2")
x := i1
y := i2
log.Printf("x= %v, y = %v, sum = %v", x, y, x+y)
}
我将程序运行了 20 次,并对每个程序的运行时间取平均值。我看平均值几乎相等?并行化不应该让事情变得更快吗?我做错了什么?
这是运行它 20 次的 python 程序:
iterCmd = 'go run iterSum.go'
parallelCmd = 'go run parallelSum.go'
runCount = 20
def analyzeCmd(cmd, runCount):
runData = []
print("running cmd (%s) for (%s) times" % (cmd, runCount))
for i in range(runCount):
┆ start_time = time.time()
┆ cmd_out = subprocess.check_call(shlex.split(cmd))
run_time = time.time() - start_time
┆ curr_data = {'iteration': i, 'run_time' : run_time}
┆ runData.append(curr_data)
return runData
iterOut = analyzeCmd(iterCmd, runCount)
parallelOut = analyzeCmd(parallelCmd, runCount)
print("iter cmd data -->")
print(iterOut)
with open('iterResults.json', 'w') as f:
json.dump(iterOut, f)
print("parallel cmd data -->")
print(parallelOut)
with open('parallelResults.json', 'w') as f:
json.dump(parallelOut, f)
avg = lambda results: sum(i['run_time'] for i in results) / len(results)
print("average time for iterSum = %3.2f" % (avg(iterOut)))
print("average time for parallelSum = %3.2f" % (avg(parallelOut)))
这是 1 次运行的输出:
average time for iterSum = 0.27
average time for parallelSum = 0.29
最佳答案
所以,这里有几个问题。首先,您的 channel 在并发示例中没有被缓冲,这意味着接收方可能仍需要相互等待一段时间。其次,并发 并不意味着并行。您确定它们实际上是并行运行的,而不是简单地安排在同一个操作系统线程上吗?
也就是说,您这里的主要问题是您的 Python 代码在每次迭代中都使用 go run,这意味着您记录的绝大部分“运行时间”实际上是 编译 你的代码(go run 编译然后运行指定的文件,它特别设计不缓存任何文件)。如果要测试运行时间,请使用 Go's benchmark system ,而不是您自己拼凑的版本。你会得到更准确的结果。例如,除了编译瓶颈之外,也没有办法确定 Python 代码本身引入了多少瓶颈。
哦,您应该改掉使用函数引用参数作为“返回”值的方式的习惯。 Go 支持多次返回,因此 C 风格的就地修改参数通常被认为是一种反模式,除非有真正令人信服的理由这样做。
关于goroutine 阻塞和非阻塞用法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48530604/
我正在学习Ruby,遇到了inject。我正处于理解它的风口浪尖,但当我是那种需要真实世界的例子来学习一些东西的人时。我遇到的最常见的例子是人们使用inject来添加一个(1..10)范围的总和,我不太关心这个。这是一个任意的例子。在实际程序中我会用它做什么?我正在学习,所以我可以继续使用Rails,但我不必有一个以Web为中心的示例。我只需要一些我可以全神贯注的目标。谢谢大家。 最佳答案 inject有时可以通过它的“其他”名称reduce更好地理解。它是一个对Enumerable进行操作(迭代一次)并返回单个值的函数。它有许多有
我在尝试使用Faraday将文件上传到网络服务时遇到问题。我的代码:conn=Faraday.new('http://myapi')do|f|f.request:multipartendpayload={:file=>Faraday::UploadIO.new('...','image/jpeg')}conn.post('/',payload)尝试发布后似乎没有任何反应。当我检查响应时this是我所看到的:#:post,:body=>#,#,@opts={}>,#],@index=0>>,#>],@ios=[#,#,@opts={}>,#],@index=0>,#],@index=0>
我使用raise(ConfigurationError.new(msg))引发错误我试着用rspec测试一下:expect{Base.configuration.username}.toraise_error(ConfigurationError,message)但这行不通。我该如何测试呢?目标是匹配message。 最佳答案 您可以使用正则表达式匹配错误消息:it{expect{Foo.bar}.toraise_error(NoMethodError,/private/)}这将检查NoMethodError是否由privateme
目录ChatGPT简介技术原理应用未来发展ChatGPT的10 种用法ChatGPT简介ChatGPT是一种基于深度学习的大型语言模型,由OpenAI公司开发。技术原理GPT是GenerativePre-trainedTransformer的缩写,意为生成式预训练变压器。它的技术原理是使用了一个基于注意力机制的变压器(Trans
我找不到任何使用Rack::Session::Cookie的简单示例,并且希望能够将信息存储在cookie中,并在以后的请求中访问它并让它过期.这些是我能找到的唯一示例:HowdoIset/getsessionvarsinaRackapp?http://rack.rubyforge.org/doc/classes/Rack/Session/Cookie.html这是我得到的:useRack::Session::Cookie,:key=>'rack.session',:domain=>'foo.com',:path=>'/',:expire_after=>2592000,:secret=
当我尝试使用“套接字”库中的方法“read_nonblock”时出现以下错误IO::EAGAINWaitReadable:Resourcetemporarilyunavailable-readwouldblock但是当我通过终端上的IRB尝试时它工作正常如何让它读取缓冲区? 最佳答案 IgetthefollowingerrorwhenItrytousethemethod"read_nonblock"fromthe"socket"library当缓冲区中的数据未准备好时,这是预期的行为。由于异常IO::EAGAINWaitReadab
我是Ruby的新手,发现以下几对令人困惑示例同样有效:File.included_modulesFile::included_modulesFile.stat('mbox')#Returnsa'#'objectFile::stat('mbox')File.new("foo.txt","w")File::new("foo.txt","w")"asdf".size#Aninstancemethod"asdf"::size2+32::send(:+,3)#AnextremeexampleFile::new,尤其是我经常遇到的东西。我的问题:如果我永远避免使用::运算符来限定除类、模块和常量之
我需要将目录中的一堆文件上传到S3。由于上传所需的90%以上的时间都花在了等待http请求完成上,所以我想以某种方式同时执行其中的几个。Fibers能帮我解决这个问题吗?它们被描述为解决此类问题的一种方法,但我想不出在http调用阻塞时我可以做任何工作的任何方法。有什么方法可以在没有线程的情况下解决这个问题? 最佳答案 我没有使用1.9中的纤程,但是1.8.6中的常规线程可以解决这个问题。尝试使用队列http://ruby-doc.org/stdlib/libdoc/thread/rdoc/classes/Queue.html查看文
如果数组只包含一个值,我想返回数组的第一个元素。目前,我使用:vals.one??vals.first:vals.presence因此:vals=[];vals.one??vals.first:vals.presence#=>nilvals=[2];vals.one??vals.first:vals.presence#=>2vals=[2,'Z'];vals.one??vals.first:vals.presence#=>[2,"Z"]是否有内置的东西可以做到这一点,或者是否有更好的设计考虑?我的用例是特定的,涉及知道从方法(将实现上述代码)中期望什么的演示者。如果这些演示者将所有返回
在SOquestion2068165一个答案提出了使用这样的东西的想法:params[:task][:completed_at]&&=Time.parse(params[:task][:completed_at])作为DRYer的说法params[:task][:completed_at]=Time.parse(params[:task][:completed_at])ifparams[:task][:completed_at]paramsHash将来自(Rails/ActionView)表单。这是众所周知的||=习语的一种推论,如果LHS不是nil/false则设置值。像这样使用&&