昨天在CSDN上看到了关于 ANIC的新闻,anic是一个处于开发过程中开源项目,建立在google code上,其讨论在google group上,但由于政府的负责任 ,已经登录不上去了,所以只看到其部分内容。
被其吸引是因为其号称“比C快、比java安全,比脚本简单”,最近一直在考虑编程模型,在由重核搭建的集群上,如何容易的写出高性能的并行程序是目前HPC领域的一个重大挑战,即使在网络应用方面由于多核、时代的到来,如何利用好多核加速自己的应用程序,也是非常现实的问题。MPI、OpenMP或者 MPI+OpenMP是目前的主流技术方案,但是MPI程序写起来困难、调试也困难,至于正确性验证也没有好的解决方案。我们目前希望在UPC的基础上,衍生出适合重核异构集群的编程模型,但是目前来看,在性能上也面临着巨大挑战,而且在实际应用中upc没有被很多用户接受。而且upc从根本上讲其在编程性上只是减少了一些繁琐工作,在难度上并没有降低,例如同步、一致性、依赖与数据竞争等问题依然需要程序员自己保证。
所以,看到anic后,特别是看到其introduction后,觉得如果真如其所说,则是非常漂亮的解决方案,但是在看了其Tutorial后,由于写的不完整,还没有体会到其在介绍中说的优点。现在将其内容放在后面,供大家欣赏,本想翻译成中文,奈何没有时间,有机会再说吧。
---------------------------------------------------
http://code.google.com/p/anic/
Introduction
The Fast Track
Want to get started with ANI right away? Head over straight to the ANI Tutorial.
Got burning philosophical questions? The FAQ is this way.
Have something to say? Join in on the official ANI discussion group.
Ready to dive straight into the source? Go right ahead.
The Quirks
Crazy? Most definitely. And yet strangely enough, it works!
Hello, World!
The language couldn't possibly be simpler...
"Hello, World!" ->std.out
Dining Philosophers Problem - A Complete, Well-Written, Correct Program
philosopher = [[int id]] {
chopstick = [[int/]] <- 0;
leftPhil = [[philosopher]];
rightPhil = [[philosopher]];
getChopsticks = [[--> int/, int/]] { /leftPhil.chopstick, /rightPhil.chopstick --> };
returnChopsticks = [[int/ cs1, int/ cs2]] { /cs1 ->leftPhil.chopstick; /cs2 ->rightPhil.chopstick; };
eat = [[int/ cs1, int/ cs2 --> int/, int/]] {
"Philosopher " + id + " eating.../n" ->std.out;
/cs1, /cs2 -->;
};
loopback => std.rand std.delay /getChopsticks eat ->returnChopsticks loopback;
};
numPhils = 5;
philStream = [[philosopher//]];
//[[std.gen]] <- numPhils {
[[philosopher]] <- {..} ->philStream;
philStream[..] ->philStream[..].leftPhil;
philStream[(.. + 1) % numPhils] ->philStream[..].rightPhil;
};
(for a more detailed explanation of why this works, see the FAQ)
Compare this with Wikipedia's much longer, much less efficient, and unintuitive Pascal solution to the problem -- and that's actually a "simple" solution leaning on high-level monitor constructions. For the real nightmare, try implementing this thing using pthreads (the industry standard). Given half an hour and some frustration, a well-experienced programmer could probably do it.
But why? There's ANI.
The Aim
While you're thinking, here's a terse but complete implementation in ANI:
@std.in;
a=[[0/]]; op=[[' '/]]; b=[[0/]]; r=[[0/]];
0 { clock => [[int ms]] { ("/r" + ms/1000.0 + ":" + a + op + b + "=" + r) ->std.out; 1 std.delay (ms+1) clock} };
inLoop => {/in->a /in->op /in->b inLoop};
//op ?? {'+': (/a+/b) '-': (/a-/b) '*': (/a*/b) '/': (/a//b) : 0} ->r;
The Bottom Line
The central philosophy of ANI programming is that you "type-and-forget". You describe what you want to happen to your data, and it just gets done -- and fast. ANI is lightweight like a shell script but fast like C, safe like Java, and implicitly massively parallel like a language for the parallel processing age should be.
ANI accomplishes these ambitious goals by way of two novel approaches:
- a paradigm shift away from the intractable chaos of imperative-style memory twiddling in favor of structured but flexible dataflow pipelines that can be heavily optimized through static analysis, and
- a paper-thin but extremely powerful micro-scheduling runtime that exploits experimental ideas such as dynamic code polymorphism to deliver fine-grained, safe, and fully implicit parallelism from the compiled pipelines