Optimize power usage in VA sharing scenarios.

- in VA sharing scenarios driver needs to be as power efficient as possible
- Added new mode to KMD notify helper called maxPowerSavingMode
- in this mode, whenever GPU is not busy, driver will choose non busy wait
path.

Change-Id: I7e4079be995107bea543ffda774ca161ce483944
This commit is contained in:
Mrozek, Michal 2018-07-31 08:38:50 +02:00 committed by sys_ocldev
parent b4b4a306d4
commit d53e1c3979
9 changed files with 85 additions and 4 deletions

View File

@ -144,6 +144,10 @@ class CommandStreamReceiver {
bool initializeTagAllocation();
KmdNotifyHelper *peekKmdNotifyHelper() {
return kmdNotifyHelper.get();
}
protected:
void setDisableL3Cache(bool val) {
disableL3Cache = val;
@ -195,6 +199,7 @@ class CommandStreamReceiver {
IndirectHeap *indirectHeap[IndirectHeap::NUM_TYPES];
std::unique_ptr<FlatBatchBufferHelper> flatBatchBufferHelper;
std::unique_ptr<ExperimentalCommandBuffer> experimentalCmdBuffer;
std::unique_ptr<KmdNotifyHelper> kmdNotifyHelper;
};
typedef CommandStreamReceiver *(*CommandStreamReceiverCreateFunc)(const HardwareInfo &hwInfoIn, bool withAubDump);

View File

@ -109,8 +109,6 @@ class CommandStreamReceiverHw : public CommandStreamReceiver {
const HardwareInfo &hwInfo;
CsrSizeRequestFlags csrSizeRequestFlags = {};
std::unique_ptr<KmdNotifyHelper> kmdNotifyHelper;
};
} // namespace OCLRT

View File

@ -31,6 +31,7 @@
#include "runtime/platform/platform.h"
#include "runtime/helpers/string.h"
#include "runtime/command_queue/command_queue.h"
#include "runtime/command_stream/command_stream_receiver.h"
#include "runtime/built_ins/built_ins.h"
#include "runtime/compiler_interface/compiler_interface.h"
#include "runtime/memory_manager/svm_memory_manager.h"
@ -174,11 +175,15 @@ bool Context::createImpl(const cl_context_properties *properties,
// We currently assume each device uses the same MemoryManager
if (devices.size() > 0) {
this->memoryManager = this->getDevice(0)->getMemoryManager();
auto device = this->getDevice(0);
this->memoryManager = device->getMemoryManager();
this->svmAllocsManager = new SVMAllocsManager(this->memoryManager);
if (memoryManager->isAsyncDeleterEnabled()) {
memoryManager->getDeferredDeleter()->addClient();
}
if (sharingBuilder->isSharingPresent(SharingType::VA_SHARING)) {
device->getCommandStreamReceiver().peekKmdNotifyHelper()->initMaxPowerSavingMode();
}
}
for (auto &device : devices) {

View File

@ -37,7 +37,9 @@ bool KmdNotifyHelper::obtainTimeoutParams(int64_t &timeoutValueOutput,
quickKmdSleepRequest |= applyQuickKmdSleepForSporadicWait();
if (!properties->enableKmdNotify && !acLineConnected) {
if (maxPowerSavingMode) {
timeoutValueOutput = 1;
} else if (!properties->enableKmdNotify && !acLineConnected) {
timeoutValueOutput = KmdNotifyConstants::timeoutInMicrosecondsForDisconnectedAcLine;
} else if (quickKmdSleepRequest && properties->enableQuickKmdSleep) {
timeoutValueOutput = properties->delayQuickKmdSleepMicroseconds;

View File

@ -64,6 +64,10 @@ class KmdNotifyHelper {
static void overrideFromDebugVariable(int32_t debugVariableValue, int64_t &destination);
static void overrideFromDebugVariable(int32_t debugVariableValue, bool &destination);
void initMaxPowerSavingMode() {
maxPowerSavingMode = true;
}
protected:
bool applyQuickKmdSleepForSporadicWait() const;
int64_t getBaseTimeout(const int64_t &multiplier) const;
@ -72,5 +76,6 @@ class KmdNotifyHelper {
const KmdNotifyProperties *properties = nullptr;
std::atomic<int64_t> lastWaitForCompletionTimestampUs{0};
std::atomic<bool> acLineConnected{true};
bool maxPowerSavingMode = false;
};
} // namespace OCLRT

View File

@ -81,6 +81,10 @@ bool SharingFactory::finalizeProperties(Context &context, int32_t &errcodeRet) {
return true;
}
bool SharingFactory::isSharingPresent(SharingType sharingId) {
return sharingContextBuilder[sharingId] != nullptr;
}
SharingBuilderFactory *SharingFactory::sharingContextBuilder[SharingType::MAX_SHARING_VALUE] = {
nullptr,
};

View File

@ -70,6 +70,7 @@ class SharingFactory {
static std::unique_ptr<SharingFactory> build();
bool processProperties(cl_context_properties &propertyType, cl_context_properties &propertyValue, cl_int &errcodeRet);
bool finalizeProperties(Context &context, int32_t &errcodeRet);
bool isSharingPresent(SharingType sharingId);
std::string getExtensions();
void fillGlobalDispatchTable();
void *getExtensionFunctionAddress(const std::string &functionName);

View File

@ -59,6 +59,7 @@ struct KmdNotifyTests : public ::testing::Test {
using KmdNotifyHelper::acLineConnected;
using KmdNotifyHelper::getMicrosecondsSinceEpoch;
using KmdNotifyHelper::lastWaitForCompletionTimestampUs;
using KmdNotifyHelper::maxPowerSavingMode;
using KmdNotifyHelper::properties;
MockKmdNotifyHelper() = delete;
@ -334,6 +335,25 @@ TEST_F(KmdNotifyTests, givenDisabledKmdNotifyMechanismWhenAcLineIsDisconnectedTh
EXPECT_EQ(10000, KmdNotifyConstants::timeoutInMicrosecondsForDisconnectedAcLine);
}
TEST_F(KmdNotifyTests, givenKmdNotifyEnabledWhenInitMaxPowerSavingModeIsCalledThenObtainReturnOneAsWaitValue) {
localHwInfo.capabilityTable.kmdNotifyProperties.enableKmdNotify = true;
MockKmdNotifyHelper helper(&(localHwInfo.capabilityTable.kmdNotifyProperties));
EXPECT_FALSE(helper.maxPowerSavingMode);
int64_t timeout = 0;
bool timeoutEnabled = helper.obtainTimeoutParams(timeout, false, 1, 2, 2);
EXPECT_TRUE(timeoutEnabled);
EXPECT_EQ(2, timeout);
helper.initMaxPowerSavingMode();
EXPECT_TRUE(helper.maxPowerSavingMode);
timeoutEnabled = helper.obtainTimeoutParams(timeout, false, 1, 2, 2);
EXPECT_TRUE(timeoutEnabled);
EXPECT_EQ(1, timeout);
}
TEST_F(KmdNotifyTests, givenEnabledKmdNotifyMechanismWhenAcLineIsDisconnectedThenDontChangeTimeoutValue) {
localHwInfo.capabilityTable.kmdNotifyProperties.enableKmdNotify = true;
localHwInfo.capabilityTable.kmdNotifyProperties.delayKmdNotifyMicroseconds = 5;

View File

@ -22,6 +22,7 @@
#include "gtest/gtest.h"
#include "runtime/context/context.h"
#include "runtime/command_stream/command_stream_receiver.h"
#include "runtime/device/device.h"
#include "runtime/helpers/string.h"
#include "runtime/platform/platform.h"
@ -196,6 +197,14 @@ TEST(SharingFactoryTests, givenMockFactoryWithSharingWhenAskedThenAddressIsRetur
EXPECT_EQ(reinterpret_cast<void *>(dummyHandler), ptr);
}
TEST(SharingFactoryTests, givenSharingFactoryWhenSharingIsRegisteredThenIsSharingPresentReflectsThatStatus) {
SharingFactoryStateRestore stateRestore;
stateRestore.clearCurrentState();
EXPECT_FALSE(stateRestore.isSharingPresent(SharingType::CLGL_SHARING));
stateRestore.registerSharing<MockSharingBuilderFactory>(SharingType::CLGL_SHARING);
EXPECT_TRUE(stateRestore.isSharingPresent(SharingType::CLGL_SHARING));
}
TEST(Context, givenMockSharingBuilderWhenContextWithInvalidPropertiesThenContextCreateShouldFail) {
SharingFactoryStateRestore stateRestore;
@ -226,3 +235,35 @@ TEST(Context, givenMockSharingBuilderWhenContextWithInvalidPropertiesThenContext
context.reset(Context::create<Context>(validProperties, deviceVector, nullptr, nullptr, retVal));
EXPECT_NE(nullptr, context.get());
};
TEST(Context, GivenVaContextWhenItIsCreatedItInitializesPowerSavingMode) {
SharingFactoryStateRestore stateRestore;
stateRestore.clearCurrentState();
stateRestore.registerSharing<MockSharingBuilderFactory>(SharingType::VA_SHARING);
std::unique_ptr<MockDevice> device(new MockDevice(*platformDevices[0]));
cl_device_id clDevice = static_cast<cl_device_id>(device.get());
DeviceVector deviceVector((cl_device_id *)&clDevice, 1);
cl_int retVal;
auto pPlatform = OCLRT::platform();
cl_platform_id platformId[1];
platformId[0] = pPlatform;
auto &commandStreamReceiver = device->getCommandStreamReceiver();
auto kmdNotifyHelper = commandStreamReceiver.peekKmdNotifyHelper();
int64_t timeout = 0;
kmdNotifyHelper->obtainTimeoutParams(timeout, true, 1, 10, 2);
EXPECT_NE(1, timeout);
cl_context_properties validProperties[5] = {CL_CONTEXT_PLATFORM, (cl_context_properties)platformId[0],
clContextPropertyMock, mockContextPassFinalize, 0};
std::unique_ptr<Context> ctx(Context::create<Context>(validProperties, deviceVector, nullptr, nullptr, retVal));
EXPECT_EQ(CL_SUCCESS, retVal);
EXPECT_NE(nullptr, ctx);
kmdNotifyHelper->obtainTimeoutParams(timeout, true, 1, 10, 2);
EXPECT_EQ(1, timeout);
}