首页 > 编程语言 >Julia中的异步编程

Julia中的异步编程

时间:2023-10-12 23:47:58浏览次数:46  
标签:异步 函数 编程 Julia 任务 take 我们 运行

在本章中,我们将学习Julia异步编程的基础知识,我们将了解:

  • tasks
  • channels

Tasks

创建任务

从技术上讲,Julia中的任务是symmetric co-routine(对称协同例程)。更通俗地说,task是一项计算工作,可以在将来的某个时刻开始安排,并且可以中断和恢复。要创建任务,我们首先需要创建一个函数来表示任务中要完成的工作。在以下代码中,我们生成一个任务,用于生成两个矩阵并对它们求和。

安排任务

任务已经创建,但是对应的工作尚未开始,我们没有看到函数的任何输出,要运行任务,我们需要进行schedule。

获取任务结果

任务已经执行了,但是看不到结果,为了获得结果,我们需要获取它。

任务异步运行

值得注意的是,任务是异步运行的,为了说明这一点,我们创建并安排一个新任务。

请注意,当任务运行的时候,我们可以执行Julia代码,比如上边的两行单元格。这是为什么呢?因为任务在后台运行,并且该特定任务的大部分时间都处于休眠。因此,在任务休眠的时候可以使用当前的Julia进程进行其他的操作。

任务不并行运行

任务不是并行运行的,我们能够在之前的任务运行时运行代码,是因为该任务在睡眠函数中大部分时间都处于空闲状态。如果任务执行实际工作,当前进程将忙于该任务并阻止运行其他任务。让我们举一个具体的例子。以下代码计算近似值pi,使用莱布尼兹公式。近似的质量随着n的增加而提高。

用一个大数调用这个函数,这需要一些时间。

然后创建执行此计算的任务。

安排任务,然后尝试执行下面的第二个单元格,请注意,当前进程将忙于运行该任务。

yield

如果任务不并行运行,那么任务的目的是什么?任务很方便,因为他们可以被中断并将控制权切换到其他任务。这是通过yield函数实现的。当我们调用yield时,我们提供了切换到另一个任务的机会。下面函数是上边函数的变体,其中我们每1000次迭代都会产生一次。在调用yield时,我们允许其他任务接管。如果没有对yield的调用,一旦我们启动函数,compute_pi,我们就无法启动任何其他的任务,直到该函数完成为止。

我们可以通过以下代码来检查此行为。在创建并安排一个使用函数计算pi的任务时,我们可以在该任务运行时运行下边的代码,因为我们经常在内部调用yield。

示例:实现sleep函数

使用yield,我们可以实现自己的sleep函数:

task采用不带参数的函数

函数需要有0个参数,但是如果需要它可以捕获变量。如果我们尝试使用带有参数的函数创建任务,那么安排它时将会导致错误。

如果需要,我们可以捕获任务运行的函数中的变量,如下面的单元格所示:

 

有用的宏:@async

到目前为止,我们已经使用低级函数创建了任务,但是还有更方便的方法来创建和调度任务。例如使用@async宏,该宏是用于异步运行一段代码。在幕后,它将代码放入匿名函数中,创建任务并安排它。以下这个单元格和之前的单元格是等价的。

另一个有用的宏:@sync

这个宏用于等待给给定代码块中所有@async创建的任务。

 

Channels

在任务之间发送数据

Julia提供channels作为在task之间发送数据的方式,channel就像一个FIFP队列,任务可以将值放入其中并从中取出值。在下一个示例中,我们创建一个channel和一个将5个值放入该channel的任务。最后,task关闭通道。

多次执行最后一行代码,我们将从channel中获取值。我们确实在传递来自两个不同task的数值。如果我们执行该单元超过5次,则会引发错误,因为通道已经关闭。

通道是可迭代的,我们可以在for循环中迭代通道,直到关闭通道,而不是从通道中获取值直到发生错误。

Calls to put! and take! are blocking

put!和take!是阻塞操作,调用put!会阻塞任务,直到另一个任务调用take!为止,反之亦然。因此,我们需要至少两个任务才能实现此目的。如果我们从同一个任务调用put!和take!,就会导致死锁。我们在前面的示例中添加了一条打印语句。再次运行它并注意如何put!阻塞,直到我们调用take!

Buffered channels

我们可以更灵活一点,使用buffered channel,在这种情况下,put!仅当通道已满时才会阻塞,take!如果通道为空则阻塞。我们重复前面的示例,但是使用大小为2的缓冲通道。请注意,我们可以调用put!直到通道已满。此时,我们需要等待,直到调用take!从通道中删除一个项目,为新项目腾出空间。

 

 

 

Questions

循环大约需要花费十倍的时间,因为运行了十次函数,所以选a。

Q2:The time in doing the loop will be almost zero since the loop just schedules 10 tasks, which should be very fast.

Q3:It will take 2.5 seconds, like in question 1. The @sync macro forces to wait for all tasks we have generated with the @async macro. Since we have created 10 tasks and each of them takes about 0.25 seconds, the total time will be about 2.5 seconds.

@async 宏用于启动异步任务,这意味着它将代码放入一个独立的任务中,不会等待该任务完成,而是会立即继续执行后续的代码。所以,如果你执行 @async a + b,它会非常快速地返回,不会等待 a + b 运行完。

@sync 宏用于等待异步任务的完成,确保在继续执行后续代码之前,所有被标记为异步的任务都已经完成。这是为了确保你的代码在需要异步任务的结果时不会过早地继续执行。

Q4:It will take about 3 seconds. The channel has buffer size 4, thus the call to put!will not block. The call to take! will not block neither since there is a value stored in the channel. The taken value is 3 and therefore we will wait for 3 seconds.

Q5:The channel is not buffered and therefore the call to put! will block. The cell will run forever, since there is no other task that calls take! on this channel.

标签:异步,函数,编程,Julia,任务,take,我们,运行
From: https://www.cnblogs.com/lbwBH/p/17760884.html

相关文章

  • socket网络编程
    Socket网络编程一、计算机网络概述1、IP地址的概念IP地址就是标识网络中设备的一个地址,好比现实生活中的家庭住址。网络设备的效果图:2、IP地址的表现形式说明:IP地址分为两类:IPv4和IPv6IPv4是目前使用的IP地址IPv6是未来使用的IP地址IPv4是由点分十进制组成IPv6是......
  • Shell(四):awk编程
    1、awk简介awk因三位缔造者的名字而命令(Aho、Weinberger和Kernighan),是一种能够对结构化数据进行操作,并产生格式化报表的编程语言。awk功能与sed相似,都是用来进行文本处理的,awk语言可以从文件或字符串中基于指定规则浏览和抽取信息,在抽取信息的基础上,才能进行其他文本......
  • JNI编程之字符串处理
    java中的字符串类型是String,对应的jni类型是jstring,由于jstring是引用类型,所以我们不能像基本数据类型那样去使用它,我们需要使用JNIEnv中的函数去处理jstring,下面介绍一些常用的字符串处理函数。1.GetStringUTFChars()作用:将jstring类型转化为c中的constchar*类......
  • golang之异步队列Asynq
    Asynq[1]是一个Go实现的分布式任务队列和异步处理库,基于redis,类似Ruby的sidekiq[2]和Python的celery[3]。Go生态类似的还有machinery[4]和goworker同时提供一个WebUI asynqmon[5],可以源码形式安装或使用Dockerimage,还可以和Prometheus集成dockerrun--rm--nameasynqmon......
  • 开发者笔记 C++11新特性并发编程future
    上一篇介绍了<thread>文件里线程相关类,这篇将介绍C++<future>头文件里线程类,future里包含的类主要是处理异步任务,线程函数封装,线程间通信,同步,捕捉异常处理https://zhuanlan.zhihu.com/p/509118687future的引入c++11引入的future是为了解决异步通信问题的。future可以看做是数......
  • 谁将是年度编程霸主?PHP 真的跌出神坛
    全球知名TIOBE编程语言社区发布的12月编程语言排行榜,有几件有趣的现象,随着小编一起看看~下个月,TOIBE年度编程语言就会公布了!该奖项是授予2021年增长最快的编程语言,目前,C#最有可能获得年度编程语言,有趣的是,在过去的21年里,C#里从来没有获得过“TIOBE索引年度编程语言奖”,尽管它在......
  • C++异步定时器设计与实现
    C++异步定时器设计与实现由于目前C++标准中没有现成的定时器,本设计使用C++11相关语法并进行封装。本定时器包含一个TimerManager类用于创建定时器和进行定时任务管理,TimerManager会创建两个线程(mTimerTickThread、mTimerCallbackThread)分别用于时间处理和函数回调。可以使用Ti......
  • Julia基础知识
    在本章中,我们将学习并行计算所需的Julia基本部分:变量函数数组在Julia中使用jupyter笔记本,运行单元格可以使用shift+enter,也可以使用运行按钮。 运行第一个单元格可以看到,显示了最后一行的值,我们可以用分号抑制输出,尝试执行第二个单元格,可以发现没有输出。单元格的顺......
  • 编程式导航——两种路由跳转方式
    编程式导航:通过JS的方式实现路由跳转如何实现点击按钮跳转? 一、不传参:1.通过path路径跳转(简易方便)①简写:  按钮的点击事件中写  this.$router.push('/路由路径')    比如:this.$router.push('/search') ②完整写法:this.$router.push({ ......
  • Julia入门
    本次并行计算课程将使用Julia编程语言,与高性能计算HPC相关的课程通常使用C、C++或者Fortran语言,Julia是一种较为新的编程语言,专为科学计算而设计。它将类似python等解释用语言的高级语法与C等编译语言的性能相结合。因此,Julia允许我们使用在教学环境中方便的语法编写高效的并行算......