-
Notifications
You must be signed in to change notification settings - Fork 396
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Migrate processor and feature detection from OpenJ9 to OMR #4339
Comments
Sure, I can definitely look into this. |
After reading through the issue and getting familiar with the code, I think I will divide this issue into 4 PRs. |
@0xdaryl that is correct, I couldn't find a better way to phrase that point. |
Update for those following: I got a working version of processor detection locally on my x86 machine. Will test other architectures, and submit a PR when all is ready! |
I was wondering how should we be testing feature detection? In my opinion, Openj9 currently has a fairly "weak" test for feature detection (https://github.com/eclipse/openj9/blob/master/runtime/tests/port/si.c#L965-L971), and I would like to improve upon this if possible... |
On Linux we can likely query |
This might have some issues where the user doesn't have permission to view the output of IMO, it's very difficult to actually precisely verify if all the known features (for a specific processor) are set... |
I would agree. We'll just have to be very diligent when manually testing that this was done right. i.e. hop on a bunch of different machines and validate before/after. Perhaps using OpenJ9 may help here since processor detection is known to work there already. |
I am currently on step 2 of resolving this issue: Implementing the port library function throughout OMR and unifying the different API calls for processor detection. One thing I noticed is that the current processor detection in 1: In the 2: In OpenJ9, reconfigure all of the instances where the old processor detection functions were use to utilize the new port library functions. 3: Safely delete the old processor detection functions from OMR. Let me know if this works! |
For clarity: |
Sounds like a good plan. |
Went through the above discussions: Here's my understanding: In OMR we have
In OpenJ9 we have
Last Week's Meeting:
@fjeremic @dsouzai Let me know if I understood everything correctly, I want to make sure everything is clear before I proceed to implementation. Thanks! @mpirvu FYI, this is the processor feature detection work for OMR that I'll be working on for a while, I will likely log all my progress in this issue. |
The initialization should happen in the constructor of the |
Had a high priority JITServer item last week, back to this work item now. Some notes about
|
Let's be consistent with other platforms. If an object can be fully initialized at the allocation point we should initialize the object in the Constructor and simplify the callers by not having to call an additional API which they may or may not be aware of. |
Summary of the Processor Detection OMR Port Library Additions
|
How OpenJ9 initializes "TR::Compiler->target.cpu" for x86
else if (TR::Compiler->target.cpu.isX86())
{
const char *vendor = TR::Compiler->target.cpu.getProcessorVendorId();
uint32_t processorSignature = TR::Compiler->target.cpu.getProcessorSignature();
TR::Compiler->target.cpu.setProcessor(portLibCall_getX86ProcessorType(vendor, processorSignature));
TR_ASSERT(TR::Compiler->target.cpu.id() >= TR_FirstX86Processor
&& TR::Compiler->target.cpu.id() <= TR_LastX86Processor, "Not a valid X86 Processor Type");
}
TR_X86CPUIDBuffer *
CPU::queryX86TargetCPUID()
{
static TR_X86CPUIDBuffer buf = { {'U','n','k','n','o','w','n','B','r','a','n','d'} };
jitGetCPUID(&buf);
return &buf;
}
TR_X86CPUIDBuffer *
OMR::X86::CPU::queryX86TargetCPUID()
{
static TR_X86CPUIDBuffer *buf = NULL;
auto jitConfig = TR::JitConfig::instance();
if (jitConfig && jitConfig->getProcessorInfo() == NULL)
{
buf = (TR_X86CPUIDBuffer *) malloc(sizeof(TR_X86CPUIDBuffer));
if (!buf)
return 0;
jitGetCPUID(buf);
jitConfig->setProcessorInfo(buf);
}
else
{
if (!buf)
{
if (jitConfig && jitConfig->getProcessorInfo())
{
buf = (TR_X86CPUIDBuffer *)jitConfig->getProcessorInfo();
}
else
{
buf = (TR_X86CPUIDBuffer *) malloc(sizeof(TR_X86CPUIDBuffer));
if (!buf)
memcpy(buf->_vendorId, "Poughkeepsie", 12); // 12 character dummy string (NIL term not used)
buf->_processorSignature = 0;
buf->_brandIdEtc = 0;
buf->_featureFlags = 0x00000000;
buf->_cacheDescription.l1instr = 0;
buf->_cacheDescription.l1data = 0;
buf->_cacheDescription.l2 = 0;
buf->_cacheDescription.l3 = 0;
}
}
}
return buf;
}
TR::CPU *
OMR::CPU::self()
{
return static_cast<TR::CPU*>(this);
}
|
This question I can answer it myself. |
The purpose of this change is to make x86 consistent with other platforms (Power, Z) which use the CPU class instead of codegen to query and cache processor related information. Issue: eclipse-omr#4339 Signed-off-by: Harry Yu <harryyu1994@gmail.com>
The purpose of this change is to make x86 consistent with other platforms (Power, Z) which use the CPU class instead of codegen to query and cache processor related information. Issue: eclipse-omr#4339 Signed-off-by: Harry Yu <harryyu1994@gmail.com>
Yes we can. Ideally as you mentioned earlier where we want to arrive at the end is for this processor detection to be migrated into the port library ( |
Issue: eclipse-omr#4339 Signed-off-by: Harry Yu <harryyu1994@gmail.com>
Issue: eclipse-omr#4339 Signed-off-by: Harry Yu <harryyu1994@gmail.com>
Issue: eclipse-omr#4339 Signed-off-by: Harry Yu <harryyu1994@gmail.com>
Issue: eclipse-omr#4339 Signed-off-by: Harry Yu <harryyu1994@gmail.com>
Issue: eclipse-omr#4339 Signed-off-by: Harry Yu <harryyu1994@gmail.com>
Issue: eclipse-omr#4339 Signed-off-by: Harry Yu <harryyu1994@gmail.com>
- Replace old processor APIs with new APIs from the CPU class - Replace global TR::Compiler target with per comp target so that each compilation can either use target or relocatableTarget depending on the type of the compilation (JIT or AOT) - When there is no port lib available, continue to use old APIs Issue: eclipse-omr#4339 Signed-off-by: Harry Yu <harryyu1994@gmail.com>
Issue: eclipse-omr#4339 Signed-off-by: Harry Yu <harryyu1994@gmail.com>
Issue: eclipse-omr#4339 Signed-off-by: Harry Yu <harryyu1994@gmail.com>
Summary of changes: - Retire old version cpu detection code on Power - Move `CPU::getProcessorDescription()` to base J9CPU class as the 3 platforms (X, Z, Power) share the same code. There is no need to have 3 copies - Reasons for the removal: - We kept the old version because we wanted to make sure new version and old version give us the same behaviour - Now it's been a few month and we don't see any bugs with the new version there's no reason to keep the old version - Also we want to prevent developers from using the old version. Old design - Initializes the `TR_Processor` struct via j9port library - Initialization occurs in `TR_J9VM::initializeProcessorType()` - obtain cpu information using `CPU::TO_PORTLIB_getJ9ProcessorDesc()` - `TR::Compiler->target.cpu.setProcessor` to set processor - Fields and methods associated with the old design live in `Class CPU` - Common APIs: - `CPU::TO_PORTLIB_getJ9ProcessorDesc()` - `j9sysinfo_processor_has_feature(processorDesc, feature)` (j9port library API) - `CPU::id()` - `CPU::setProcessor(TR_Processor)` New design - Initializes the `OMRProcessorDesc` struct via omrport library - `CPU::detect()` to initialize `OMRProcessorDesc processorDescription` - `CPU::applyUserOptions()` to apply any debug options after initialization - `TR::Compiler->target.cpu` singleton variable that holds the CPU instance - `comp()->target().cpu` per compilation variable which is used for cross-cpu compilation support - For JIT we initialize `comp()->target().cpu` with `TR::Compiler->target.cpu` (Host CPU) - For AOT we initialize `comp()->target().cpu` with `TR::Compiler->relocatableTarget.cpu` (Portable CPU) - Fields and methods associated with the new design live in `Class CPU` - Common APIs: - `CPU::supportsFeature(feature)` - `CPU::isAtLeast(OMRProcessorArchitecture)` - Benefits: - Common to all 3 platforms - Simpler interface - Cross-CPU compilation support (Use one cpu for AOT and another for JIT) - The implementation for the new design is first introduced here eclipse-omr/omr#5197 and eclipse-openj9#9571 issue: eclipse-omr/omr#4339 depends on: eclipse-omr/omr#5547 Signed-off-by: Harry Yu <harryyu1994@gmail.com>
Latest Changes:Summary of changes:
Old design
New design
Introduce Feature Masks
|
@fjeremic @dsouzai : There are a lot of detailed comments in this issue tracking the progress of this work (thanks @harryyu1994!). However, can one of you please provide a summary of what work remains to be done from its current state? @nbhuiyan will return to the port library initialization problem soon (he's working on a PR) which will make the port lib accessible within OMR and should deprecate some of the duplicate code within OMR itself. |
AFAIK the detection has been sunk into OMR and there are two main pieces still remaining to finish:
|
Just stumbled on eclipse-openj9/openj9#12670 where it seems we have duplicated code for processor detection in OpenJ9. We need to remove this as part of the migration effort here to avoid developers adding more code into the OpenJ9 versions. @nbhuiyan wondering if you have a timeline to resume this work? |
@fjeremic I plan on resuming this work later this week or early next week. |
While fixing a bug to make sure we do vectorize some of the vector API intrinsics for Float type (On Z, we need to have I guess continuing discussion from Filip's comment, if we have hooked up the port library to compiler, we can clean-up the old checks so that we would not use them accidentally. Trying to find out in the code-base, if we ever had change for hooking up portlib to compiler but can not find. @0xdaryl @nbhuiyan did we finished working on remaining pieces of work for this issue and can the code-gen go ahead and clean-up old feature detection code? [1]. https://github.com/eclipse/omr/blob/edf2ae5033cb412348dbeb74d31bab2d26fe933d/compiler/z/env/OMRCPU.cpp#L101-L102 |
@r30shah I had the work to support the port library usage in the compiler completed a few months ago, but I was not able to get around to opening a PR for it yet. I am working on that and will update this issue soon. |
Thanks a lot @nbhuiyan , We will wait for your PR before cleaning up the old processor feature recognition code. Trying to understand so as for current state, in the function supportsFeature we are not guaranteed to have |
Currently while within the OMR Compiler, there is no guarantee that the port library is initialized. This is because OMR Compiler-based projects can initialize the compiler without the port library, which made it necessary to perform the check for the port library when used within OMR Compiler code. Given that the flags necessary for the old API is never set currently, |
Background
The CPU class in the compiler in OMR [1] currently has no way of determining the processor we are running on at runtime. The
OMR::CPU
class is an extensible class which is meant to be overriden by the target code generator. Inside of these extended codegen classes we have APIs to determine whether we support generating instructions for a particular processor. For example [2] is the override on Z and [3] is the override on Power.Each code generator seems to use different, although quite similar APIs to determine if we can generate instructions for a particular processor.
TR::Compiler->target.cpu.id()
TR::Compiler->target.cpu.getSupportsArch()
cg()->getX86ProcessorInfo()
As we can see we're somewhat inconsistent in the APIs we use. More over, if you notice the APIs we use across the different codegens will always default down to the minimum Architecture Level Set (ALS) defined in OMR. This means that irregardless of what processor we are actually running on we'll generate instructions for the least supported processor.
This is problematic in dynamic runtimes.
[1] https://github.com/eclipse/omr/blob/20db4fbc1ea570fd806783a97b16831f4f719eed/compiler/env/OMRCPU.cpp
[2] https://github.com/eclipse/omr/blob/20db4fbc1ea570fd806783a97b16831f4f719eed/compiler/z/env/OMRCPU.cpp
[3] https://github.com/eclipse/omr/blob/20db4fbc1ea570fd806783a97b16831f4f719eed/compiler/p/env/OMRCPU.cpp
[4] https://github.com/eclipse/omr/blob/20db4fbc1ea570fd806783a97b16831f4f719eed/compiler/p/codegen/BinaryEvaluator.cpp#L2087-L2096
[5] https://github.com/eclipse/omr/blob/20db4fbc1ea570fd806783a97b16831f4f719eed/compiler/z/codegen/BinaryEvaluator.cpp#L3125-L3128
[6] https://github.com/eclipse/omr/blob/20db4fbc1ea570fd806783a97b16831f4f719eed/compiler/x/codegen/OMRCodeGenerator.cpp#L385-L388
Proposed Solution
Our friends at the OpenJ9 project have implemented processor detection in the port library already, and the JIT compiler in OpenJ9 is already making use of the data provided by the port library and caching the various answers for use in the JIT.
For example on Power and Z we use the
j9sysinfo_processor_has_feature
API [7] to query whether we have support for a particular CPU feature, which is initialized in the port library on initialization. Example of this is in thej9sysinfo.c
file for both Power and Z [8].Similarly processors are detected via the
J9ProcessorDesc
struct which is initialized via thej9sysinfo_get_processor_description
API which can be found in the samej9sysinfo.c
file. The way in which we initialize these structures depends on the OS and architecture type.What we effectively need to do is to sink the OpenJ9 pieces of the processor and feature detection down into the OMR layer so that we can access it directly from the OMR compiler. The work here will involve investigating what pieces of the OpenJ9 port library are used and finding the correct place to move the APIs in OMR. Processor and feature detection is a delicate piece of OpenJ9 and is crucial for performance so such a change must be staged, that is to first copy the processor detection into OMR, make use of it in OMR, only once that is working we can work on deprecating the OpenJ9 piece to take advantage of the OMR support.
[7] https://github.com/eclipse/openj9/blob/82609efc1fa05a5d1af51ad6ceed7215376dde84/runtime/compiler/z/env/J9CPU.cpp#L230-L301
[8] https://github.com/eclipse/openj9/blob/82609efc1fa05a5d1af51ad6ceed7215376dde84/runtime/port/unix/j9sysinfo.c
The text was updated successfully, but these errors were encountered: