Omr: JitBuilder services have no way to detect platform features

Created on 20 Dec 2016  路  7Comments  路  Source: eclipse/omr

It came up that atomic add support had not been added to all code generators and so, when JitBuilder tests were run on POWER or Z, they would fail. JitBuilder has not needed an API to describe available hardware features before. Atomic adds are, I believe, supported by the hardware we target just not by all our code generators just yet. Hardware transactional memory, however, is not always available on all supported hardware platforms, and so new services like those proposed in #610 are not always guaranteed to be available. The fact that the OMR compiler has no locking primitives makes this problem especially troublesome for atomics and transactional memory.

We need to figure out if JitBuilder should have an API to query such things, or if the services should return values to indicate they are not able to work on the current hardware. Should the onus to do the right thing be on JitBuilder or on the client? i.e. Is it ok for JitBuilder to have services that may not be usable on the current hardware system?

jitbuilder discussion

Most helpful comment

Should the onus to do the right thing be on JitBuilder or on the client? i.e. Is it ok for JitBuilder to have services that may not be usable on the current hardware system?

I think this question will come up again and again every time someone needs/wants to do more than what JitBuilder currently does. If we keep adding things to JitBuilder it's going to grow to be as complex as the stuff it's claiming to simplify, which is counter-productive. On the other hand if we keep JitBuilder simple it's users will inevitably outgrow it once they need/want to do more.

Personally I'd lean towards the latter, keep it dead simple and straight forward and be OK with people outgrowing it. It's going to be very hard to come up with an interface that's easy to pick up and does everything for everybody.

Specifically for the questions above, let the user figure it out. For querying hardware caps we have a port library that's supposed to make this sort of thing easier. For invoking functionality that's not implemented in certain backends let it blow up with an assertion, or let the compilation fail with suitable verbose output; it provides more motivation for someone to go and actually implement it.

All 7 comments

Should the onus to do the right thing be on JitBuilder or on the client? i.e. Is it ok for JitBuilder to have services that may not be usable on the current hardware system?

I think this question will come up again and again every time someone needs/wants to do more than what JitBuilder currently does. If we keep adding things to JitBuilder it's going to grow to be as complex as the stuff it's claiming to simplify, which is counter-productive. On the other hand if we keep JitBuilder simple it's users will inevitably outgrow it once they need/want to do more.

Personally I'd lean towards the latter, keep it dead simple and straight forward and be OK with people outgrowing it. It's going to be very hard to come up with an interface that's easy to pick up and does everything for everybody.

Specifically for the questions above, let the user figure it out. For querying hardware caps we have a port library that's supposed to make this sort of thing easier. For invoking functionality that's not implemented in certain backends let it blow up with an assertion, or let the compilation fail with suitable verbose output; it provides more motivation for someone to go and actually implement it.

Thanks @ymanton !

@charliegracie or @Leonardo2718 : opinions, since you're also actively using JitBuilder?

My initial reaction is the same as @ymanton. JitBuilder is supposed to be easy and straight forward. I think that if a runtime needs more features than JitBuilder provides it may be time for that runtime to move beyond JitBuilder and implement an IlBuilder.

I am completely ok with runtime assertions for features that are not supported on a given platform.

This is not dissimilar to an item on my 2017 wish list for test. For test, I'd like to see a few functions added to the port library that can return information about the hardware / software capabilities on the machines. I could then call this API from my test setup and make a run-time decision on whether to run or skip particular tests. If this API lives in the port library, we could presumably leverage this solution in all runtimes sitting atop OMR, so that I'd have a way to dynamically determine the tests to run.

For Java tests, we'd tag tests using testng groups and compare whether machine capabilities matched the tags on the test itself. We could add a similar tagging capability to googletest or use its existing filtering/naming capabilities to do same for native test. Any other language using OMR has potentially this same (test) requirement.

I agree with @ymanton and @charliegracie on this one. If a user want's that level of control then they've likely outgrown JitBuilder.

To summarize, the consensus is:

  1. require clients to test for platform support requirements based on the port library
  2. introduce assertions in those services that rely on features and just blow up if they are used in places where they aren't supported.

I completely agree the platform tests should be ultimately implemented via a common port library layer, but confess I am bothered a bit by the "figure it out yourself" approach:

  • does not make it easy for JitBuilder clients to build a robust compiler unless they limit themselves to (an unspecified list of) services that are supported on all platforms
  • problems only show up when the JitBuilder compiler or its generated code is run on some platform the compiler writer didn't anticipate (so it's hurting both the compiler writer and that compiler writer's user) with some arcane assertion or broken code
  • encourages "unmanaged" (i.e. hard to intercept) code that should run only on the target platform which isn't necessarily the platform where the compiler is running

What if JitBuilder could give conservative notions of broad categories of runtime platform support just as a guide? Maybe services like SupportTransactions() or SupportVector() or SupportAtomicOperations(). The API could be segmented into sections so that the recommendation could be that, if you use a service from category X, you should make sure that "SupportsX()" return true before you use it. If you don't, you're in your own hands so be careful.

I don't think that would make the API that much more cumbersome and it would provide an important aspect of documentation (which otherwise needs to be explained). More advanced users who know exactly what they're doing can devise their own tests and use the services without necessarily gating on the general SupportsX() query. It would be better if there was a way to express those tests as part of the JitBuilder API, but I share the concern with the API becoming more cumbersome if we do that.

Maybe there's another way to solve the "this code must run on the target machine" issue, i.e. force the client to provide some code that will run on the target platform (sort of like how users have to write their own TypeDictionary if they want to define their own types). I'll leave this to another issue.

Any additional thoughts @ymanton @charliegracie @Leonardo2718 @smlambert ?

What if JitBuilder could give conservative notions of broad categories of runtime platform support just as a guide? Maybe services like SupportTransactions() or SupportVector() or SupportAtomicOperations(). The API could be segmented into sections so that the recommendation could be that, if you use a service from category X, you should make sure that "SupportsX()" return true before you use it. If you don't, you're in your own hands so be careful.

That might be the most reasonable thing to do if we want JitBuilder users to have both a simple interface and access to more hardware dependent features. (Although the code that @fredqiu checked in for JitBuilder transactions does supposedly fall back "gracefully" if the processor doesn't support transactions. I say "gracefully" because what it does is throw away everything but the persistent failure path of the transaction, however the code in your persistent failure path is not necessarily what you would want executed if you had no transactional memory support whatsoever...)

Having said that, what I was originally getting at is that I don't think we can or should prevent people from outgrowing JitBuilder and should establish where JitBuilder's boundaries are. Users may eventually either want or need to do things that JitBuilder doesn't allow on many different fronts -- IL, code gen, code layout, dispatch, linkage, types, metadata, GC integration -- do we extend JitBuilder to allow for these things? Is JitBuilder supposed to be a simple path to compiled code that's intended for prototyping and experimenting, or is it intended to eventually support mature, complicated language frontends?

As an example, vector support might actually be very hairy. Some platforms tolerate operating on unaligned data with only modest performance penalties (x86, new Power), some tolerate it but with severe penalties (older Power), some don't tolerate it at all and produce either incorrect results or exceptions (Power) and some are many of the above, depending on the actual particular processor, what mode it's booted in, what mode the kernel is in, and who knows what else (Power, ARM) -- a simple SupportVector() wouldn't capture that, so what would JitBuilder's vector support have to look like to address the 3 bullet points above?

Was this page helpful?
0 / 5 - 0 ratings