并发编程语言(Concurnas Programming Language)

2020-05-28 04:55:54

Concurnas是一种开源的JVM编程语言,旨在构建可靠、可扩展、高性能的并发、分布式和并行系统。

使用Concurnas使并发和并行编程变得更容易,从而帮助组织充分利用现代多核CPU和GPU硬件。

Concurnas可与Java(和其他JVM语言)互操作-组织能够在并发环境中利用现有的Java软件。

与其他语言相比,使用Concurnas开发人员需要编写的代码行更少。该代码更安全、更易于测试,从而提高了质量并提高了开发人员的工作效率。

受Python和Java等语言的启发,Concurnas是一种静态类型的垃圾回收语言,它利用易于学习的语法进行类型推理。

Concurnas是一种在Java虚拟机上运行的编译语言,因此可以访问JVM提供的难以置信的性能。

Concurnas使从小型研究原型到全球范围的分布式生产解决方案使用相同的代码成为可能。

Concurnas是一项开源技术,可以自由使用和修改。由Concurnas Ltd提供的持续开发和商业支持

Concurnas@JAX伦敦2020.。我们将在2020伦敦JAX大会上谈论Concurnas。

Concurnas提供了一个简单但极其强大的并发模型,它允许您编写并发代码,而不必编写样板代码来管理线程、临界区或锁!

Concurnas作为并发计算的专门化,为分布式计算提供了一流的公民支持。

Concurnas为GPU编程提供一流的公民支持。您可以用惯用的Concurnas代码编写代码并在GPU上运行,而不必切换到C/C++!

Concurnas为与非堆管理、非垃圾回收的内存交互提供了一流的公民支持。这使得使用GPU、大数据和自定义数据库变得轻而易举。

Concurnas支持现代命令式计算中使用的所有常用构造,例如:if-Elif-Else、for、while循环、断言、异常。加上来自块的隐式返回,以及语句、列表理解、复印机等等!

Concurnas从面向对象编程中去掉了繁重的工作和繁琐的工作,让它再次变得有趣起来。Concurnas高级支持类(具体、抽象、继承)、泛型(输入、输出、通配符、有界)、枚举、注释。以及诸如特征、元组、对象提供程序、类型定义、基于用法的泛型类型推断、类字段getter/setter的自动生成/重定向、类散列代码和等式等新特性。

函数式编程范例结合了一组非常有用的解决问题的方法,但是纯函数式编程在世界上很少见。在Concurnas中,我们采用了函数式编程中使用最广泛的元素,并将它们集成到Concurnas中。使用Concurnas,您可以访问方法和函数引用、lambdas、部分函数求值、惰性求值、模式匹配等等!

Concurnas对新兴的反应式编程范例拥有一流的公民支持。使用Concurnas,您可以编写自动响应输入参数更改的代码,从而允许您创建反应式管道。一种非常自然的解决算法问题的方法。

Concurnas为核心数据结构(包括数组、矩阵、列表、映射、范围和集合)提供了一流的公民支持。

Concurnas是一种在科学计算社区中流行的技术,它允许您通过一个字符运算符将运算符应用于数组/矩阵/列表的所有元素。

Concurnas提供独立编译器、交互式REPL shell、Jupyter Notebook、VS Code、Atom和Sublime Text支持。

Concurnas是一种空安全语言,这有助于消除现代编程中最常见的错误来源之一:空指针异常!

Concurnas在Java虚拟机上运行,这不仅让您可以访问JDK和JVM提供的出色的多平台性能,而且还可以与其他JVM语言(如Java、Scala、Kotlin和Clojure)兼容-此外,您可以轻松地集成/使用所有现有的JVM代码,而无需修改。

Concurnas是一种静态类型语言,它广泛使用类型推理来消除类型负担。通常情况下,Concurnas代码与Python代码(被广泛认为是最容易编码的语言之一)没有什么区别,但具有Java的性能!

编程语言不仅仅是机器用的--人们也需要阅读它们!Concurnas提供了简洁的语法和许多快捷方式,使编写易于阅读和维护的代码成为规范。对于需要额外清晰度的代码,Concurnas也可以冗长。

Concurnas通过表达式列表、扩展函数和运算符重载对特定于域的语言提供广泛支持。Concurnas还支持语言扩展,允许您将非Concurnas代码段直接嵌入到Concurnas代码文件中。

def gcd(x int,y int){//两个整数的最大公约数While(Y){(x,y)=(y,x mod y)}x}calc1=gcd(8,20)!//在隔离calc2=gcd(6,45)中运行此计算!//如果calc1>;calc2否则calc2,请在单独的隔离calc3=calc1中运行此计算//^等待calc1的结果。

Concurnas允许您通过使用bang!在单独的线程型容器(称为隔离)中轻松地并发执行计算!接线员。

并发计算通常被认为是现代软件工程中最困难的方面之一。

请注意并发计算是如何在Concurnas中成为一行程序的,创建/管理线程、线程池、生命周期、锁(或死锁!)、临界区、同步、等待、通知线程等都不用担心。所有这些困难的事情都会自动处理-让您专注于重要的事情。

n=10 nplusone={n+=1;n}!//在一个分离物中执行此计算,n的副本为nminusone={n-=1;n}!//另一个分离物在n的单独副本上//以上两个分离物永远不会相互干扰。n//nplusone==11//nminusone==9。

Concurnas中的所有代码都在隔离中执行。隔离被映射到运行代码的机器的底层硬件线程上。隔离器在其自己的专用内存空间内运行。

将复制隔离中使用的所有状态,但引用、参与者和一些特殊标记的可共享类除外。这种状态隔离使推理和设计并发算法变得更容易,因为它减少了为同步和竞争条件编写代码的需要。

AREF INT://这是一个INT{//并发执行的复杂隔离最终设置AREF.//此处的复杂代码.AREF=10}!//AREF';需要其当前值:RESULT INT=AREF//如果尚未设置任何值,执行将暂停System.out.println(";AREF的值为:";+RESULT)。

execcount int:=0 for(A In 1 To 10){//一些复杂的计算..execount++}!//生成隔离以并发执行上述操作。等待(execount;execount==10)//暂停进一步执行,直到execount==10。

aval int://未设置初始值bval int:=22//初始值已知SUMMARTS int:=EVERY(aval,bval){aval+bval}//以上初始化后,允许执行.aval=100 bval=200//上面的每个块都将并发运行,并最终将SUMMICS设置为:AWAIT(SUMMILES;SUMMILES==300)。

它们不是在隔离之间复制,而是共享,但提供对其可变状态的受控原子访问。如果请求时尚未在REF上设置值,则暂停执行,并允许执行其他隔离,直到设置了值,之后继续执行。

我们可以通过Concurnas提供的以下反应式编程构造对引用的更改做出反应:

等待将暂停执行,直到在REF上设置了值并且满足了可选的保护条件。

onchange将在其监视的任何引用发生更改时触发其代码块的并发执行。

每个参数的行为与onchange相同,但如果在任何受监视的引用上设置了初始值,则会触发

a int:b int:c<;=a+b//相同于:C int:=Every(a,b){a+b}d<;-a+b//相同于:C int:=onchange(a,b){a+b}。

与Concurnas的大多数语法元素一样,提供了反应式编程构造Every and OnChange的简明版本。这有效地将反应式计算变成了一行操作。

count1 int:=100 count2 int:=100 onchange(count1,count2){System.out.println(";sum:{count1+count2}";)}trans{count1-=10 count2+=10}//将输出:";sum:200";

Concurnas通过TRANS BLOCK关键字支持软件事务内存。这允许我们对一个或多个引用进行更改,并使这些更改在事务之外以原子为基础可见。

来自com.concurnas.lang.Pulsar导入Pulsar,RealtimePulsar来自java.time导入持续时间Pulsar=new RealtimePulsar()oneOffTrigger:=10秒时间内的pulsar.after(Duration.ofSeconds(10))//schedule事件.每个(OneOffTrigger){System.out.println(";当前时间:";+oneOffTrigger)}//每2秒安排10次事件.RepeatingTrigger:=Pulsar.Repeat(Duration.ofSecond(2),10)每(RepeatingTrigger){System.out.println(";当前时间:";+RepeatingTrigger)}。

并发系统工程中的一种常见模式是希望有一些基于时间的触发器,等待10秒,然后执行x";或每隔3秒做一次y等,或在此特定时间执行此操作。在Concurnas,我们将此称为时间计算。

时间计算通过内置的Pulsar库得到支持,该库位于:com.concurnas.lang.Pulsar。此库允许我们将活动安排在经过一定时间后在将来进行。它还允许我们为将来的重复安排任务。

Concurnas提供脉冲星的实时实现和冰冻时间实现(主要用于测试时间应用),允许时间作为受控变量注入。

result=parfor(b in 0到10){gcd(b,10-b)}//result==[10:,1:,2:,5:,2:,1:,2:,1:,10:]。

Concurnas拥有对并行for循环的头等公民支持。这些是用于在循环上下文中并行执行基于任务的操作的方便而直观的机制。它们与Concurnas中的常规循环具有相同的语法。

ACTOR MyActor{//让我们定义一个ACTOR-count=0 def Increment(){count++}}//使用上面的ACTOR:ma=new MyActor()ma.incremental()//就像正常的方法调用一样,将阻塞,直到执行完成sync{//sync-等待块中创建的所有隔离完成{ma.increate()}!//并发调用{ma.increate()}!}count=ma.getCount()//count==3,这是不可能的。

Concurnas中的参与者使我们能够构建微服务。每个参与者都在自己的专用隔离内运作。从调用代码的角度来看,参与者的外观和行为与常规对象一样。

参与者允许我们以单线程样式编写服务代码,并且能够以并发方式安全地运行它们,而不必担心同步或争用条件,因为对参与者的每个调用都是按顺序运行的,并且在完成之前具有对参与者状态的独占访问权限。自然,因为参与者实现了他们自己的并发控制,所以无需跨多个隔离进行复制就可以安全地共享它们。

class MyCounter(-count int){//普通类def increment(){count++}}//我们现在可以通过of关键字定义和使用我们的类型化执行元,如下所示:Actor MyActor of MyCounter(0)//让我们使用新的类型化执行元:ma=new MyActor()ma.incremental()sync{//sync-等待块中创建的所有隔离完成ma.increate()!ma.increate()!}count=ma.count//count==3。

有时我们没有从零开始定义演员的奢侈。如果我们使用的是预先存在的代码,情况尤其如此。为此,Concurnas提供了类型化的参与者。类型化的参与者构造它们自己的角色,并围绕一个普通对象的实例。

用于创建被包装的类或方法的实例的任何构造函数也由类型化参与者提供。

class MyCounter(-count int){def increate(){count++}}inst1=执行元MyCounter(0)//在MyCounter上新建执行元inst2=new执行元MyCounter(0)//在MyCounter上创建新执行元。

创建类型化执行元的另一种方法是,在创建对象的实例(现在是AND ACTOR!)时,只需使用ACTOR关键字代替或附加于NEW关键字。

//一个简单的矩阵乘法内核.gpukernel 2 matMult(M int,K int,GLOBAL in A Float[2],GLOBAL in B Float[2],GLOBAL OUT result Mat Float[2]){globalRow=get_global_id(0)globalCol=get_global_id(1)acc=0.0f;for(k=0;k<;K;k++){acc+=A[k*M+globalRow]*B[globalCol*K+k]}。

Concurnas拥有GPU计算的一流市民支持。GPU可以像CPU协处理器一样使用,通过它们的使用,我们经常能够将许多计算限制问题的计算速度提高100倍以上,而不是传统的基于CPU的计算。

GPU计算的核心是内核。这些都是在我们的GPU上执行的,以便执行计算。Concurnas允许您使用Concurnas编程语言的子集创建内核。这意味着我们只需稍加修改就可以编写惯用的并发代码,以便在GPU上执行计算。

//在GPU设备上创建数组缓冲区ar gpus.GPUBufferInput=device.makeOffHeapArrayMixed<;int[]>;(int[].class,10)//将数据从堆复制到缓冲区.copy Complete布尔值:gps.GPURef=ar.writeToBuffer([1 2 3 4 5 6 7 8 9 10])//在我们等待复制完成的同时,可能在GPU上执行其他计算.await(Copy Complete)//a仅输入缓冲区ar gpus.GPUBufferInput=device.makeOffHeapArrayIn<;int[]>;(INT[].class,10)//a 2 x 4输出矩阵矩阵垫gpus.GPUBufferOutput=device.makeOffHeapArrayOut<;int[2]>;(int[2].class,2,4)。

当我们检查要在GPU上执行的算法时,通常它们设计和使用的一个重要因素是与GPU之间的数据传输有关。Concurnas为此过程提供专门的支持。

一些最高效的GPU算法通过同时实现数据传输和计算的流水线来实现它们的效率,从而使GPU始终忙于做有用的工作。Concurnas凭借其对非阻塞GPU操作(如通过Refs进行数据传输)的本机支持,使得这一点变得很容易。

//定义符合C99的原始OpenCL C代码:@GPUStubFunction(Source=";Float plus1(Float a,Float b){return a+b;}";)gpudef plus1(a Float,b Float)Float//使用现有的符合C99的OPENCL C代码:@GPUStubFunction(sources=[';./cpucode.cl';,';./gpuutilCode.cl';])gpudef plus2(a Float,b Float)Float。

Concurnas使用OpenCL实现GPU计算。这是有利的,因为除了其多供应商支持(主要是英特尔、NVIDIA和AMD)外,用户还可以访问用于GPU计算的整个现有库代码。

Concurnas允许以两种方式之一使用现有代码,要么直接通过用符合C99的OpenCL C代码编写的代码字符串使用,要么作为附加到存根内核的注释中的直接文件引用。

//一种利用GPU本地内存gpukernel 2matMultLocal(M int,N int,K int,常量A浮点[2],常量B浮点[2],GLOBAL OUT RESULT FLOAT[2]){row=get_local_id(0)col=get_local_id(1)globalRow=CacheSize*get_group_id(0)+row//结果行(0..M)globalCol=CacheSize*get_group_id(1)+colof result(0..N)//本地内存保存缓存A和B中的CacheSize元素*CacheSize元素。CacheSize]acc=0.0f//循环遍历所有分片cacheSize int=K/CacheSize for(t=0;t<;cacheSize;t++){//将全局内存中的A和B的一段缓存//到本地内存tiledRow=CacheSize*t+row tiledCol=CacheSize*t+colcacheA[ol][row]=A[tiledCol*M+globalRow]cacheb[ol][row]=B[globalCol*K+tiledRow]屏障(True)/。k++){//累加矩阵子部分的结果acc+=cacheA[k][row]*cacheb[ol][k]}屏障(True)//确保在移动到下一个缓存节之前完成所有工作项}result[globalCol*M+globalRow]=acc}。

Concurnas具有对本地GPU内存和屏障的本地惯用支持。通常,当在GPU上使用本地内存实现空间局部性很强的算法时,它们会在性能方面受益良多。

Concurnas GPU实施提供了详细的性能分析选项。这对于开发、使人能够调试GPU代码以便确定执行某些操作所花费的时间以及用于监视目的都是有用的。

//远程服务器:reMServer=new com.concurnas.lang.Dist.RemoteServer(port=42001)remServer.startServer()//等到终止remServer.close()。

//客户端:rm=Remote(';localhost';,port=42001)//远程执行代码,返回ref:ans int:={10+10}!(rm.onailReter())rm.close()//ans==20

Concurnas为分布式计算提供了一种易于使用、直观和非侵入式的解决方案,它是对并发计算隔离模型的扩展。通过这种方式,我们能够使用我们已经习惯/已经使用的并发计算模型来构建我们的软件,并且可以很容易地将其扩展到远程工作。通过这种方式,当我们的计算需求增长时,我们可以很容易地扩展我们的解决方案来适应。

Concurnas抽象化了许多关于管理分布式计算的艰苦工作,使我们能够专注于我们试图解决的更有趣的问题。例如,使用Concurnas,远程服务器将缓存结果,并在发生网络故障时等待客户端重新连接。

//远程服务器:reMServer=new com.concurnas.lang.Dist.RemoteServer()//使用默认端口42000 remServer.startServer()//等到终止remServer.close()。

类MyCalculator{//依赖代码-callCounter=0//两个整数的最大公约数.def gcd(x int,y int){//+计数器和Result While(Y){(x,y)=(y,x mod y)}";count:{++callCounter},result:{x}";}}//远程连接并执行RM=Remote(';127.0.0.1';)//使用默认端口42000结果=try{calc=MyCalculator()calc.gcd(344756)//还传输依赖代码(MyCalculator.class)和对象状态(CallCounter).res字符串:={calc.gcd(97,7081)}!(rm.onailReter())res:get()}Finally{rm.close()}//result==count:2,result:97。

使用Concurnas,可以对远程服务器进行配置,以便它们可以运行提交给它们的任何被认为可以安全执行的代码。

内部Concurnas分布式计算API包括对依赖关系解析的规定,该依赖关系解析本身相当复杂,并且为了提高性能,能够执行静态代码依赖关系分析,以便预先确定并抢先提供执行所需的代码。

..