ezesdk/java

Moderator: michal.warecki

ezesdk/java

Postby notzed » Sun Jun 01, 2014 11:24 am

I've recently gotten back to continuing my quest to create an alternative/experimental/prototyping loader/runtime for the epiphany and this weekend I finally added some Java interfaces to it. As people might have noticed - using the parallella sdk which requires linker scripts and so on is really just a bit archaic and it was just way too much pain for me to put up with for very long.

From the Java side it basically works a bit like OpenCL where the Java can be used to load 'workgroups of kernels' (small stand-alone but multi-core programs, not full-blown C apps) onto the epiphany cores from source or pre-compiled binaries, look up symbols by name and communicate with them. It's lower level though and all the ipc is up to the programmer.

I've been using the C implementation to experiment the epiphany but didn't want to deal with it for GUI functionality so added the Java stuff. Although it's far from complete and i'm still experimenting with almost everything I have enough to write a JavaFX frontend to an epiphany Mandelbrot Set generator - kinda boring but it demonstrates that some of it works.

I posted about it: http://a-hackers-craic.blogspot.com.au/ ... -demo.html

Since there seems to be approximately zero interest in the ezesdk stuff so far let alone the Java bit I don't feel particularly driven to drop a new release out that includes this stuff but I will probably do one in the next few days just to checkpoint the work so far.
notzed
 
Posts: 331
Joined: Mon Dec 17, 2012 12:28 am
Location: Australia

Re: ezesdk/java

Postby castan » Mon Jun 02, 2014 11:32 am

It's not "zero interest", at least one (myself) !

Thanks for this job. I will try it .
castan
 
Posts: 5
Joined: Mon Dec 17, 2012 3:22 am

Re: ezesdk/java

Postby shodruk » Tue Jun 03, 2014 4:26 am

That's a great step, keep going on! :D
Shodruky
shodruk
 
Posts: 464
Joined: Mon Apr 08, 2013 7:03 pm

Re: ezesdk/java

Postby notzed » Tue Jun 03, 2014 4:42 am

castan wrote:It's not "zero interest", at least one (myself) !

Thanks for this job. I will try it .


Only approximately zero :)

FWIW i just uploaded 0.2 which includes the java stuff and demo. It needs java8 (i.e. from oracle) and JDK_HOME defined before running make.

http://www.users.on.net/notzed/software/ezesdk.html
notzed
 
Posts: 331
Joined: Mon Dec 17, 2012 12:28 am
Location: Australia

Re: ezesdk/java

Postby over9000 » Fri Jun 20, 2014 1:04 am

Hmm.. absolutely not zero interest, though I can take or leave the Java side...

So I've been playing with one of my new boards for about three days on and off. Just getting stuff working and looking at examples (and getting those to work too). Your stuff was the next thing that I wanted to get around to looking at, and I'm impressed.

I love the way the output files are statically linked against the support libs that do the symbol lookups. Much nicer than the system of setting up environment variables in order to get any of the official examples to work.

The thing that I really hate about the esdk is the hard-coding of addresses. I'd love to see a better scheme that lets the programmer effectively declare shared variables (and higher-level constructs) without having to hard-code where they are in a particular segment or global address and do all the calculations themselves. My idea for handling this would be to have a simple declarative language for defining the I/O requirements of the program (in terms of primitives like queues/streams, mutexes, barriers or whatever), with stubs to allow insertion of C code to respond to things in an event-like fashion. This would then be compiled into a set of host and device C files. Your framework looks like it would be a nice backend to target something like that to.

I've not looked at the code in great detail, but I've picked up a fairly good idea of how it works from your posts (here and on the blog) and the associated documentation/tests. A couple more thoughts occur to me, though..

First, just wondering why you abandoned the ELF loader work you were doing? I thought it worked pretty well on PS3. On a related note, do you have to lock pages into memory on the host side? Is that done automatically?

The other thing I was wondering was about memoising the symbol lookups. I haven't looked into that part of the code, but it seems from the output of the test programs that the device side does a new call to the host every time it wants to find the address of a symbol. Obviously, if the program is aware that it's going to need the symbol again, it can stash the address itself to avoid extra overheads, but it does take away from the transparency aspect. Also, I guess you can cache the value on the host side, but again there's the issue of latency, depending on how quickly the host can respond to requests. I ended up thinking about whether a trampoline-style setup could be used. You'd have to replace actual variable names with macros on the device side (EZ_SHARED(variable)), and also maybe have a separate "declarative" macro. These would basically translate into function calls returning the address value. Initially, they could be laid out like:

Code: Select all
 label_x:  call deref_x
  data 'name of symbol'
 deref_x: call host_lookup (with address of string already on stack)


Then have host_lookup modify that whole block of code so that it instead returns the memoised value of the symbol lookup?

I know that this sort of thing (replacing actual variables with macros) does break some things like treating the variable as an lvalue, but since we're only talking about addresses, that shouldn't be too big a problem, and anyway, I foresee that eventually this sort of thing (accessing remote memory locations) would be used more for generated code (which could handle more complex structures) than necessarily someone would write by hand...

Maybe I'm way off the mark with this idea, but I thought I'd share it with you anyway. It's a nice project and definitely something I'll try to find time to dig into.

Cheers!
over9000
 
Posts: 98
Joined: Tue Aug 06, 2013 1:49 am

Re: ezesdk/java

Postby Transcendental » Fri Jun 20, 2014 2:18 pm

+1 for "interested in your project"
User avatar
Transcendental
 
Posts: 49
Joined: Mon Dec 17, 2012 1:41 am

Re: ezesdk/java

Postby Gravis » Fri Jun 27, 2014 3:58 pm

i think the best way to get java running on epiphany is to make a LLVM backend. right now, there is a java bytecode frontend, so a backend would complete the translation.
User avatar
Gravis
 
Posts: 445
Joined: Mon Dec 17, 2012 3:27 am
Location: East coast USA.

Re: ezesdk/java

Postby notzed » Mon Jun 30, 2014 1:57 am

Gravis wrote:i think the best way to get java running on epiphany is to make a LLVM backend. right now, there is a java bytecode frontend, so a backend would complete the translation.


This has nothing to do with running java on the epiphany, just using java as the host/gui language. At this point i'm only running C or assembly on-chip.
notzed
 
Posts: 331
Joined: Mon Dec 17, 2012 12:28 am
Location: Australia

Re: ezesdk/java

Postby notzed » Mon Jun 30, 2014 6:00 am

over9000 wrote:Hmm.. absolutely not zero interest, though I can take or leave the Java side...

So I've been playing with one of my new boards for about three days on and off. Just getting stuff working and looking at examples (and getting those to work too). Your stuff was the next thing that I wanted to get around to looking at, and I'm impressed.

I love the way the output files are statically linked against the support libs that do the symbol lookups. Much nicer than the system of setting up environment variables in order to get any of the official examples to work.

The thing that I really hate about the esdk is the hard-coding of addresses. I'd love to see a better scheme that lets the programmer effectively declare shared variables (and higher-level constructs) without having to hard-code where they are in a particular segment or global address and do all the calculations themselves. My idea for handling this would be to have a simple declarative language for defining the I/O requirements of the program (in terms of primitives like queues/streams, mutexes, barriers or whatever), with stubs to allow insertion of C code to respond to things in an event-like fashion. This would then be compiled into a set of host and device C files. Your framework looks like it would be a nice backend to target something like that to.


The hard-coding addresses was pretty much the main reason for doing it, and having to deal with linker scripts, neither of which a programmer should have to deal with outside of writing operating system kernels. Initially I just used a script to extract symbol addresses at compile time and turn them into a header of defines - but it was clumsy and a error prone and not something I could see anyone wanting to use.

I've got some other ideas but I haven't gotten around to trying them out yet (motivation is a bit lacking of late but due to external factors). They mostly revolve around job queues and executing small kernels and generally abstracting the details away from the code.

BTW the host libezehost.so is still a dynamic library, I just use the -R option to point to it in the makefile so i can run it without having to set LD_LIBRARY_PATH. It's not really a production thing but it makes it easier to play with and avoids the pain of libtool. The epiphany code is statically linked but it is with the esdk as well - although you need to use those linker scripts. Some of the stuff is hard-coded to my board too and I wasn't sure if it would work elsewhere.

I've not looked at the code in great detail, but I've picked up a fairly good idea of how it works from your posts (here and on the blog) and the associated documentation/tests. A couple more thoughts occur to me, though..

First, just wondering why you abandoned the ELF loader work you were doing? I thought it worked pretty well on PS3. On a related note, do you have to lock pages into memory on the host side? Is that done automatically?


It's still there, it's just wrapped in some higher level stuff primarily to support multi-core work-groups with heterogeneous code blocks (or: different code on different cores within the work-group). The original code only implemented loading code for a single core but it can now load different programmes into different cores and resolve addresses across them.

The linux kernel handles the 32MB shared memory block in that it is at a fixed physical address in the memory map and i'm just using mmap to map it to the same address as it is on the epiphany side to simplify everything (but this isn't necessary). The kernel maps the block as non-cacheable automatically so that it can be used for ipc without having to worry about the details.

The other thing I was wondering was about memoising the symbol lookups. I haven't looked into that part of the code, but it seems from the output of the test programs that the device side does a new call to the host every time it wants to find the address of a symbol. Obviously, if the program is aware that it's going to need the symbol again, it can stash the address itself to avoid extra overheads, but it does take away from the transparency aspect. Also, I guess you can cache the value on the host side, but again there's the issue of latency, depending on how quickly the host can respond to requests. I ended up thinking about whether a trampoline-style setup could be used. You'd have to replace actual variable names with macros on the device side (EZ_SHARED(variable)), and also maybe have a separate "declarative" macro. These would basically translate into function calls returning the address value. Initially, they could be laid out like:

Code: Select all
 label_x:  call deref_x
  data 'name of symbol'
 deref_x: call host_lookup (with address of string already on stack)


Then have host_lookup modify that whole block of code so that it instead returns the memoised value of the symbol lookup?


Oh no, all symbols are resolved by the linker at load time: the device never needs to call back to the host for any addresses. What you're probably looking at is the debug/output from the loader which is doing the lookups during the "runtime link". I can go into more detail on this if you like but basically the 'loader' is doing some of the linking at run-time which allows it to move bits of code (based on section boundaries) or data anywhere it likes and the code itself is the same as if it was linked at compile time.

The host code needs to do symbol lookups because nothing is resolved until run-time, and in any event it isn't linked with the epiphany code either (embedded elf as with ps3 is a bit too complex here). But since things can be stashed into a struct it can get away with very few. Only the host can allocate dynamic memory too (and only shared memory at that).

To get addresses of variables other cores one does need to explicitly write code to perform some arithmetic because each address would normally resolve to multiple cores and I couldn't think of a clean way to define which one you were after. I guess if the symbol was globally unique across all cores because that program was only loaded onto a single core then it could resolve it directly but this might have other side effects and is only a limited case.

So for example if you have two separate programs:

Code: Select all
// prog a
int a EZ_SECTION(.bss.bank0);
extern int b;


Code: Select all
// prog b
int b EZ_SECTION(.bss.bank0);
extern int a;


loaded into two separate cores:
Code: Select all
 
core  program  symbol  value
 0,0    a               a          0x2000
 0,1    b               b          0x2000


Each symbol will have the same address, and locally 'b' in 'prog a' will also be equal to 0x2000 (note that the symbol namespace is global across all programs loaded).

For program a to access b though it needs to resolve the address based on the location of the other core in the workgroup:

Code: Select all
 
int *bp = ez_global_addr(&b, 0, 1)


The only mechanism I could think of to do it at runtime was to include the information in the symbol name but that seemed clumsy. e.g. in prog a you could use perhaps:

Code: Select all
extern int b$0$1;


i.e. access symbol b from a program at core 0,1 in the workgroup. But then you need to write that every time you use it. It also only resolves to a single specific core which isn't that useful (well, it could be relative too which could be useful).

Although as I am typing this up I thought of another approach: a relocation section could be defined directly in C code which let you include any sort of mapping you wanted. The loader would interpret these tables and then discard the results as it does with other reloc information. Macros would simplify their creation.

Code: Select all
// define b to be on remote core 0,1 relative to the workgroup
extern int b;
EZ_REF(b, 0, 1);

// define b to be on remote core +1,0 relative to this core
extern int b;
EZ_REF_RELATIVE(b, +1, 0);


I guess the same table or another could be used to define other resources and avoid the need to write initialisation or setup code for them (mailboxes, mutexes and so on). It's something i'll investigate anyway.

FWIW If trampolines were used the loader can also dynamically create the code for them at link time too and so pre-resolve it before the epiphany executes.

Having control of the loader allows for a great deal of flexibility.

I know that this sort of thing (replacing actual variables with macros) does break some things like treating the variable as an lvalue, but since we're only talking about addresses, that shouldn't be too big a problem, and anyway, I foresee that eventually this sort of thing (accessing remote memory locations) would be used more for generated code (which could handle more complex structures) than necessarily someone would write by hand...

Maybe I'm way off the mark with this idea, but I thought I'd share it with you anyway. It's a nice project and definitely something I'll try to find time to dig into.

Cheers!


Well I hope the explanation above covers this - unless I misunderstood. The whole point is to be 'easy', for me too: i let the compiler/linker do most of the work and leverage as much of what the esdk toolchain/libc etc does as possible. The goal is that everything still runs as it would as if it were fully linked at compile time - which makes the code smaller and faster.
notzed
 
Posts: 331
Joined: Mon Dec 17, 2012 12:28 am
Location: Australia

Re: ezesdk/java

Postby notzed » Mon Jun 30, 2014 7:15 am

Hmm, actually maybe the $$ syntax might be useful after-all. I looked at implementing it using a table in a separate section but for various reasons i'm not finding it as nice as I thought it would be.

With some macros it might not be too clumsy to create mangled references which can be resolved at runtime link time.

Code: Select all
#define REF(v, r, c) $_ ## r ## $_ ## c ## $_ ## v
#define REF_REL(v, r, c) $ ## r ## $ ## c ## $_ ## v

extern int REF(a, 1, 2);
extern int REF_REL(a, 255, 1);

int refabs(void) {
  return REF(a, 1, 2);
}

int refrel(void) {
  return REF_REL(a, 255, 1);
}


_$_1$_2$_a = resolve 'a' at absolute coordinates 1,2
_$255$1$_a = resolve 'a' at relative coordinates -1,1 (8-bit twos complement numbers as core coordinates)

further thinking about it: actually, i'm not sure it's worth it; it doesn't make much difference (if any) to the code-size, and it forces each core to be linked individually even if it's running the same programme - which is a lot more on-host work which isn't a zero-cost either. Maybe one of the reasons I abandoned the idea initially.

Still, there may be some use for a separate section for resource definitions.
notzed
 
Posts: 331
Joined: Mon Dec 17, 2012 12:28 am
Location: Australia

Next

Return to Java

Who is online

Users browsing this forum: No registered users and 1 guest