mirror of
https://github.com/intel/compute-runtime.git
synced 2025-12-21 09:14:47 +08:00
Revert "fix: use condition variables instead of busy waits in worker threads"
This reverts commit 9d1da44e08.
Signed-off-by: Compute-Runtime-Validation <compute-runtime-validation@intel.com>
This commit is contained in:
committed by
Compute-Runtime-Automation
parent
ac296f76ba
commit
bafb847c73
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
namespace NEO {
|
namespace NEO {
|
||||||
|
|
||||||
TEST(DirectSubmissionControllerTestsMt, givenDirectSubmissionControllerWhenNewSubmissionThenDirectSubmissionsAreChecked) {
|
TEST(DirectSubmissionControllerTestsMt, givenDirectSubmissionControllerWhenTimeoutThenDirectSubmissionsAreChecked) {
|
||||||
MockExecutionEnvironment executionEnvironment;
|
MockExecutionEnvironment executionEnvironment;
|
||||||
executionEnvironment.prepareRootDeviceEnvironments(1);
|
executionEnvironment.prepareRootDeviceEnvironments(1);
|
||||||
executionEnvironment.initializeMemoryManager();
|
executionEnvironment.initializeMemoryManager();
|
||||||
@@ -28,56 +28,29 @@ TEST(DirectSubmissionControllerTestsMt, givenDirectSubmissionControllerWhenNewSu
|
|||||||
EngineDescriptorHelper::getDefaultDescriptor({aub_stream::ENGINE_CCS, EngineUsage::regular},
|
EngineDescriptorHelper::getDefaultDescriptor({aub_stream::ENGINE_CCS, EngineUsage::regular},
|
||||||
PreemptionMode::ThreadGroup, deviceBitfield)));
|
PreemptionMode::ThreadGroup, deviceBitfield)));
|
||||||
csr.setupContext(*osContext.get());
|
csr.setupContext(*osContext.get());
|
||||||
|
csr.initializeTagAllocation();
|
||||||
|
*csr.tagAddress = 9u;
|
||||||
|
csr.taskCount.store(9u);
|
||||||
|
|
||||||
DirectSubmissionControllerMock controller;
|
DirectSubmissionControllerMock controller;
|
||||||
executionEnvironment.directSubmissionController.reset(&controller);
|
executionEnvironment.directSubmissionController.reset(&controller);
|
||||||
controller.timeoutElapsedReturnValue.store(TimeoutElapsedMode::fullyElapsed);
|
controller.timeoutElapsedReturnValue.store(TimeoutElapsedMode::fullyElapsed);
|
||||||
controller.registerDirectSubmission(&csr);
|
|
||||||
controller.startThread();
|
controller.startThread();
|
||||||
// Controlling not started, wait until controller thread is waiting on condition var, no work done
|
|
||||||
while (!controller.waitOnConditionVar.load()) {
|
|
||||||
std::this_thread::yield();
|
|
||||||
}
|
|
||||||
|
|
||||||
EXPECT_TRUE(controller.waitOnConditionVar.load());
|
|
||||||
EXPECT_FALSE(controller.handlePagingFenceRequestsCalled.load());
|
|
||||||
EXPECT_FALSE(controller.sleepCalled.load());
|
|
||||||
EXPECT_FALSE(controller.checkNewSubmissionCalled.load());
|
|
||||||
|
|
||||||
// Start controlling, no submissions yet, wait until controller thread is waiting on condition var again
|
|
||||||
controller.waitOnConditionVar.store(false);
|
|
||||||
EXPECT_FALSE(controller.waitOnConditionVar.load());
|
|
||||||
csr.startControllingDirectSubmissions();
|
csr.startControllingDirectSubmissions();
|
||||||
while (!controller.waitOnConditionVar.load()) {
|
controller.registerDirectSubmission(&csr);
|
||||||
|
|
||||||
|
while (controller.directSubmissions[&csr].taskCount != 9u) {
|
||||||
std::this_thread::yield();
|
std::this_thread::yield();
|
||||||
}
|
}
|
||||||
EXPECT_TRUE(controller.waitOnConditionVar.load());
|
while (!controller.directSubmissions[&csr].isStopped) {
|
||||||
EXPECT_TRUE(controller.handlePagingFenceRequestsCalled.load());
|
|
||||||
EXPECT_TRUE(controller.sleepCalled.load());
|
|
||||||
EXPECT_FALSE(controller.checkNewSubmissionCalled.load());
|
|
||||||
|
|
||||||
// Wake up controller with new submissions, work should be done and wait again
|
|
||||||
controller.waitOnConditionVar.store(false);
|
|
||||||
controller.handlePagingFenceRequestsCalled.store(false);
|
|
||||||
controller.sleepCalled.store(false);
|
|
||||||
EXPECT_FALSE(controller.waitOnConditionVar.load());
|
|
||||||
EXPECT_FALSE(controller.handlePagingFenceRequestsCalled.load());
|
|
||||||
EXPECT_FALSE(controller.sleepCalled.load());
|
|
||||||
csr.taskCount = 10;
|
|
||||||
controller.notifyNewSubmission();
|
|
||||||
while (!controller.waitOnConditionVar.load()) {
|
|
||||||
std::this_thread::yield();
|
std::this_thread::yield();
|
||||||
}
|
}
|
||||||
// Work is done, verify results
|
{
|
||||||
EXPECT_TRUE(controller.waitOnConditionVar.load());
|
std::lock_guard<std::mutex> lock(controller.directSubmissionsMutex);
|
||||||
EXPECT_TRUE(controller.handlePagingFenceRequestsCalled.load());
|
EXPECT_NE(controller.directSubmissionControllingThread.get(), nullptr);
|
||||||
EXPECT_TRUE(controller.sleepCalled.load());
|
EXPECT_TRUE(controller.directSubmissions[&csr].isStopped);
|
||||||
EXPECT_TRUE(controller.checkNewSubmissionCalled.load());
|
EXPECT_EQ(controller.directSubmissions[&csr].taskCount, 9u);
|
||||||
EXPECT_NE(controller.directSubmissionControllingThread.get(), nullptr);
|
}
|
||||||
EXPECT_TRUE(controller.directSubmissions[&csr].isStopped.load());
|
|
||||||
EXPECT_EQ(10u, controller.directSubmissions[&csr].taskCount.load());
|
|
||||||
EXPECT_EQ(10u, csr.peekTaskCount());
|
|
||||||
|
|
||||||
controller.stopThread();
|
controller.stopThread();
|
||||||
controller.unregisterDirectSubmission(&csr);
|
controller.unregisterDirectSubmission(&csr);
|
||||||
executionEnvironment.directSubmissionController.release();
|
executionEnvironment.directSubmissionController.release();
|
||||||
@@ -89,11 +62,9 @@ TEST(DirectSubmissionControllerTestsMt, givenDirectSubmissionControllerWithStart
|
|||||||
EXPECT_NE(controller.directSubmissionControllingThread.get(), nullptr);
|
EXPECT_NE(controller.directSubmissionControllingThread.get(), nullptr);
|
||||||
controller.startControlling();
|
controller.startControlling();
|
||||||
|
|
||||||
while (!controller.waitOnConditionVar.load()) {
|
while (!controller.sleepCalled) {
|
||||||
std::this_thread::yield();
|
std::this_thread::yield();
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_TRUE(controller.waitOnConditionVar.load());
|
|
||||||
controller.stopThread();
|
controller.stopThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,11 +73,9 @@ TEST(DirectSubmissionControllerTestsMt, givenDirectSubmissionControllerWithNotSt
|
|||||||
controller.startThread();
|
controller.startThread();
|
||||||
EXPECT_NE(controller.directSubmissionControllingThread.get(), nullptr);
|
EXPECT_NE(controller.directSubmissionControllingThread.get(), nullptr);
|
||||||
|
|
||||||
while (!controller.waitOnConditionVar.load()) {
|
while (!controller.sleepCalled) {
|
||||||
std::this_thread::yield();
|
std::this_thread::yield();
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_TRUE(controller.waitOnConditionVar.load());
|
|
||||||
controller.stopThread();
|
controller.stopThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,67 +91,29 @@ TEST(DirectSubmissionControllerTestsMt, givenDirectSubmissionControllerWhenEnque
|
|||||||
DirectSubmissionControllerMock controller;
|
DirectSubmissionControllerMock controller;
|
||||||
controller.sleepCalled.store(false);
|
controller.sleepCalled.store(false);
|
||||||
controller.startThread();
|
controller.startThread();
|
||||||
|
while (!controller.sleepCalled) {
|
||||||
// No fence requests, wait until controller thread is waiting on condition var
|
|
||||||
while (!controller.waitOnConditionVar.load()) {
|
|
||||||
std::this_thread::yield();
|
std::this_thread::yield();
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_TRUE(controller.waitOnConditionVar.load());
|
|
||||||
EXPECT_FALSE(controller.handlePagingFenceRequestsCalled.load());
|
|
||||||
EXPECT_EQ(0u, csr.pagingFenceValueToUnblock);
|
EXPECT_EQ(0u, csr.pagingFenceValueToUnblock);
|
||||||
|
|
||||||
// Wake up controller with paging fence, work should be done and wait again
|
|
||||||
controller.waitOnConditionVar = false;
|
|
||||||
EXPECT_FALSE(controller.waitOnConditionVar.load());
|
|
||||||
|
|
||||||
controller.enqueueWaitForPagingFence(&csr, 10u);
|
controller.enqueueWaitForPagingFence(&csr, 10u);
|
||||||
while (!controller.waitOnConditionVar.load()) {
|
// Wait until csr is not updated
|
||||||
|
while (csr.pagingFenceValueToUnblock == 0u) {
|
||||||
std::this_thread::yield();
|
std::this_thread::yield();
|
||||||
}
|
}
|
||||||
EXPECT_TRUE(controller.waitOnConditionVar.load());
|
|
||||||
EXPECT_TRUE(controller.sleepCalled.load());
|
|
||||||
EXPECT_TRUE(controller.handlePagingFenceRequestsCalled.load());
|
|
||||||
EXPECT_EQ(10u, csr.pagingFenceValueToUnblock);
|
EXPECT_EQ(10u, csr.pagingFenceValueToUnblock);
|
||||||
|
|
||||||
// Reset test state
|
// Verify that controller is able to handle requests during controlling
|
||||||
controller.waitOnConditionVar.store(false);
|
|
||||||
controller.handlePagingFenceRequestsCalled.store(false);
|
|
||||||
controller.sleepCalled.store(false);
|
|
||||||
EXPECT_FALSE(controller.waitOnConditionVar.load());
|
|
||||||
EXPECT_FALSE(controller.handlePagingFenceRequestsCalled.load());
|
|
||||||
EXPECT_FALSE(controller.sleepCalled.load());
|
|
||||||
|
|
||||||
// Start controlling, no submissions yet, wait until controller thread is waiting on condition var again
|
|
||||||
controller.startControlling();
|
controller.startControlling();
|
||||||
while (!controller.waitOnConditionVar.load()) {
|
|
||||||
std::this_thread::yield();
|
|
||||||
}
|
|
||||||
EXPECT_TRUE(controller.waitOnConditionVar.load());
|
|
||||||
EXPECT_TRUE(controller.handlePagingFenceRequestsCalled.load());
|
|
||||||
EXPECT_TRUE(controller.sleepCalled.load());
|
|
||||||
EXPECT_FALSE(controller.checkNewSubmissionCalled.load());
|
|
||||||
|
|
||||||
// Reset test state again
|
|
||||||
controller.waitOnConditionVar.store(false);
|
|
||||||
controller.handlePagingFenceRequestsCalled.store(false);
|
|
||||||
controller.sleepCalled.store(false);
|
|
||||||
EXPECT_FALSE(controller.waitOnConditionVar.load());
|
|
||||||
EXPECT_FALSE(controller.handlePagingFenceRequestsCalled.load());
|
|
||||||
EXPECT_FALSE(controller.sleepCalled.load());
|
|
||||||
|
|
||||||
// Wake with peging fence in controlling state
|
|
||||||
controller.enqueueWaitForPagingFence(&csr, 20u);
|
controller.enqueueWaitForPagingFence(&csr, 20u);
|
||||||
while (!controller.waitOnConditionVar.load()) {
|
|
||||||
|
while (csr.pagingFenceValueToUnblock == 10u) {
|
||||||
std::this_thread::yield();
|
std::this_thread::yield();
|
||||||
}
|
}
|
||||||
EXPECT_TRUE(controller.waitOnConditionVar.load());
|
|
||||||
EXPECT_TRUE(controller.handlePagingFenceRequestsCalled.load());
|
|
||||||
EXPECT_TRUE(controller.sleepCalled.load());
|
|
||||||
EXPECT_TRUE(controller.checkNewSubmissionCalled.load());
|
|
||||||
EXPECT_EQ(20u, csr.pagingFenceValueToUnblock);
|
EXPECT_EQ(20u, csr.pagingFenceValueToUnblock);
|
||||||
|
|
||||||
controller.stopThread();
|
controller.stopThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace NEO
|
} // namespace NEO
|
||||||
@@ -5,16 +5,12 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "shared/test/common/mocks/mock_memory_manager.h"
|
|
||||||
#include "shared/test/common/mocks/mock_usm_memory_reuse_cleaner.h"
|
#include "shared/test/common/mocks/mock_usm_memory_reuse_cleaner.h"
|
||||||
#include "shared/test/common/test_macros/test.h"
|
#include "shared/test/common/test_macros/test.h"
|
||||||
namespace NEO {
|
namespace NEO {
|
||||||
|
|
||||||
TEST(UnifiedMemoryReuseCleanerTestsMt, givenUnifiedMemoryReuseCleanerWhenCachesAreEmptyThenWorkerThreadIsWaitingOnConditionVar) {
|
TEST(UnifiedMemoryReuseCleanerTestsMt, givenUnifiedMemoryReuseCleanerWhenSleepExpiredThenTrimOldInCachesIsCalled) {
|
||||||
MockMemoryManager mockMemoryManager;
|
MockUnifiedMemoryReuseCleaner cleaner(false);
|
||||||
mockMemoryManager.executionEnvironment.unifiedMemoryReuseCleaner.reset(new MockUnifiedMemoryReuseCleaner(false));
|
|
||||||
MockUnifiedMemoryReuseCleaner &cleaner = *static_cast<MockUnifiedMemoryReuseCleaner *>(mockMemoryManager.executionEnvironment.unifiedMemoryReuseCleaner.get());
|
|
||||||
|
|
||||||
cleaner.callBaseStartThread = true;
|
cleaner.callBaseStartThread = true;
|
||||||
cleaner.callBaseTrimOldInCaches = false;
|
cleaner.callBaseTrimOldInCaches = false;
|
||||||
EXPECT_EQ(nullptr, cleaner.unifiedMemoryReuseCleanerThread);
|
EXPECT_EQ(nullptr, cleaner.unifiedMemoryReuseCleanerThread);
|
||||||
@@ -24,34 +20,12 @@ TEST(UnifiedMemoryReuseCleanerTestsMt, givenUnifiedMemoryReuseCleanerWhenCachesA
|
|||||||
EXPECT_TRUE(cleaner.keepCleaning.load());
|
EXPECT_TRUE(cleaner.keepCleaning.load());
|
||||||
|
|
||||||
EXPECT_FALSE(cleaner.trimOldInCachesCalled);
|
EXPECT_FALSE(cleaner.trimOldInCachesCalled);
|
||||||
auto svmAllocCache = std::make_unique<SVMAllocsManager::SvmAllocationCache>();
|
cleaner.registerSvmAllocationCache(nullptr);
|
||||||
|
|
||||||
constexpr size_t svmAllocSize = 1024;
|
|
||||||
mockMemoryManager.usmReuseInfo.init(svmAllocSize, svmAllocSize);
|
|
||||||
svmAllocCache->memoryManager = &mockMemoryManager;
|
|
||||||
cleaner.registerSvmAllocationCache(svmAllocCache.get());
|
|
||||||
EXPECT_TRUE(cleaner.runCleaning.load());
|
EXPECT_TRUE(cleaner.runCleaning.load());
|
||||||
|
|
||||||
// Caches are empty, ensure cleaner thread is waiting on condition var
|
while (false == cleaner.trimOldInCachesCalled) {
|
||||||
while (!cleaner.waitOnConditionVar.load()) {
|
|
||||||
std::this_thread::yield();
|
std::this_thread::yield();
|
||||||
}
|
}
|
||||||
EXPECT_TRUE(cleaner.waitOnConditionVar.load());
|
|
||||||
EXPECT_TRUE(cleaner.isEmpty());
|
|
||||||
EXPECT_FALSE(cleaner.trimOldInCachesCalled);
|
|
||||||
|
|
||||||
// Wake cleaner thread to proceed some data
|
|
||||||
cleaner.waitOnConditionVar.store(false);
|
|
||||||
EXPECT_FALSE(cleaner.waitOnConditionVar.load());
|
|
||||||
SvmAllocationData allocData{0};
|
|
||||||
svmAllocCache->insert(svmAllocSize, nullptr, &allocData, false);
|
|
||||||
while (!cleaner.waitOnConditionVar.load()) {
|
|
||||||
std::this_thread::yield();
|
|
||||||
}
|
|
||||||
EXPECT_TRUE(cleaner.waitOnConditionVar.load());
|
|
||||||
EXPECT_TRUE(cleaner.isEmpty());
|
|
||||||
EXPECT_TRUE(cleaner.trimOldInCachesCalled);
|
|
||||||
|
|
||||||
cleaner.stopThread();
|
cleaner.stopThread();
|
||||||
EXPECT_EQ(nullptr, cleaner.unifiedMemoryReuseCleanerThread);
|
EXPECT_EQ(nullptr, cleaner.unifiedMemoryReuseCleanerThread);
|
||||||
EXPECT_FALSE(cleaner.runCleaning.load());
|
EXPECT_FALSE(cleaner.runCleaning.load());
|
||||||
@@ -69,4 +43,4 @@ TEST(UnifiedMemoryReuseCleanerTestsMt, givenUnifiedMemoryReuseCleanerWithNotStar
|
|||||||
cleaner.stopThread();
|
cleaner.stopThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace NEO
|
} // namespace NEO
|
||||||
@@ -1302,7 +1302,7 @@ SubmissionStatus CommandStreamReceiverHw<GfxFamily>::flushSmallTask(LinearStream
|
|||||||
this->latestSentTaskCount = taskCount + 1;
|
this->latestSentTaskCount = taskCount + 1;
|
||||||
auto submissionStatus = flushHandler(batchBuffer, getResidencyAllocations());
|
auto submissionStatus = flushHandler(batchBuffer, getResidencyAllocations());
|
||||||
if (submissionStatus == SubmissionStatus::success) {
|
if (submissionStatus == SubmissionStatus::success) {
|
||||||
++taskCount;
|
taskCount++;
|
||||||
}
|
}
|
||||||
return submissionStatus;
|
return submissionStatus;
|
||||||
}
|
}
|
||||||
@@ -1478,7 +1478,6 @@ inline bool CommandStreamReceiverHw<GfxFamily>::initDirectSubmission() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,10 +64,6 @@ void DirectSubmissionController::startThread() {
|
|||||||
void DirectSubmissionController::stopThread() {
|
void DirectSubmissionController::stopThread() {
|
||||||
runControlling.store(false);
|
runControlling.store(false);
|
||||||
keepControlling.store(false);
|
keepControlling.store(false);
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(condVarMutex);
|
|
||||||
condVar.notify_one();
|
|
||||||
}
|
|
||||||
if (directSubmissionControllingThread) {
|
if (directSubmissionControllingThread) {
|
||||||
directSubmissionControllingThread->join();
|
directSubmissionControllingThread->join();
|
||||||
directSubmissionControllingThread.reset();
|
directSubmissionControllingThread.reset();
|
||||||
@@ -75,9 +71,7 @@ void DirectSubmissionController::stopThread() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DirectSubmissionController::startControlling() {
|
void DirectSubmissionController::startControlling() {
|
||||||
std::lock_guard<std::mutex> lock(condVarMutex);
|
this->runControlling.store(true);
|
||||||
runControlling.store(true);
|
|
||||||
condVar.notify_one();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *DirectSubmissionController::controlDirectSubmissionsState(void *self) {
|
void *DirectSubmissionController::controlDirectSubmissionsState(void *self) {
|
||||||
@@ -87,13 +81,9 @@ void *DirectSubmissionController::controlDirectSubmissionsState(void *self) {
|
|||||||
if (!controller->keepControlling.load()) {
|
if (!controller->keepControlling.load()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_lock<std::mutex> lock(controller->condVarMutex);
|
std::unique_lock<std::mutex> lock(controller->condVarMutex);
|
||||||
while (!controller->runControlling.load() && controller->keepControlling.load() && controller->hasNoWork()) {
|
|
||||||
controller->wait(lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
controller->handlePagingFenceRequests(lock, false);
|
controller->handlePagingFenceRequests(lock, false);
|
||||||
|
|
||||||
auto isControllerNotified = controller->sleep(lock);
|
auto isControllerNotified = controller->sleep(lock);
|
||||||
if (isControllerNotified) {
|
if (isControllerNotified) {
|
||||||
controller->handlePagingFenceRequests(lock, false);
|
controller->handlePagingFenceRequests(lock, false);
|
||||||
@@ -106,37 +96,18 @@ void *DirectSubmissionController::controlDirectSubmissionsState(void *self) {
|
|||||||
if (!controller->keepControlling.load()) {
|
if (!controller->keepControlling.load()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_lock<std::mutex> lock(controller->condVarMutex);
|
std::unique_lock<std::mutex> lock(controller->condVarMutex);
|
||||||
while (controller->keepControlling.load() && controller->hasNoWork()) {
|
|
||||||
controller->wait(lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
controller->handlePagingFenceRequests(lock, true);
|
controller->handlePagingFenceRequests(lock, true);
|
||||||
|
|
||||||
auto isControllerNotified = controller->sleep(lock);
|
auto isControllerNotified = controller->sleep(lock);
|
||||||
if (isControllerNotified) {
|
if (isControllerNotified) {
|
||||||
controller->handlePagingFenceRequests(lock, true);
|
controller->handlePagingFenceRequests(lock, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
controller->checkNewSubmissions();
|
controller->checkNewSubmissions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DirectSubmissionController::notifyNewSubmission() {
|
|
||||||
if (this->hasNoWork()) {
|
|
||||||
++activeSubmissionsCount;
|
|
||||||
std::lock_guard<std::mutex> lock(condVarMutex);
|
|
||||||
condVar.notify_one();
|
|
||||||
} else {
|
|
||||||
++activeSubmissionsCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DirectSubmissionController::hasNoWork() {
|
|
||||||
return (0 == pagingFenceRequestsCount) && (0 == activeSubmissionsCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DirectSubmissionController::checkNewSubmissions() {
|
void DirectSubmissionController::checkNewSubmissions() {
|
||||||
auto timeoutMode = timeoutElapsed();
|
auto timeoutMode = timeoutElapsed();
|
||||||
if (timeoutMode == TimeoutElapsedMode::notElapsed) {
|
if (timeoutMode == TimeoutElapsedMode::notElapsed) {
|
||||||
@@ -170,7 +141,6 @@ void DirectSubmissionController::checkNewSubmissions() {
|
|||||||
csr->stopDirectSubmission(false, false);
|
csr->stopDirectSubmission(false, false);
|
||||||
state.isStopped = true;
|
state.isStopped = true;
|
||||||
shouldRecalculateTimeout = true;
|
shouldRecalculateTimeout = true;
|
||||||
--activeSubmissionsCount;
|
|
||||||
}
|
}
|
||||||
state.taskCount = csr->peekTaskCount();
|
state.taskCount = csr->peekTaskCount();
|
||||||
} else {
|
} else {
|
||||||
@@ -308,19 +278,17 @@ void DirectSubmissionController::recalculateTimeout() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DirectSubmissionController::enqueueWaitForPagingFence(CommandStreamReceiver *csr, uint64_t pagingFenceValue) {
|
void DirectSubmissionController::enqueueWaitForPagingFence(CommandStreamReceiver *csr, uint64_t pagingFenceValue) {
|
||||||
std::lock_guard lock(condVarMutex);
|
std::lock_guard lock(this->condVarMutex);
|
||||||
pagingFenceRequests.push({csr, pagingFenceValue});
|
pagingFenceRequests.push({csr, pagingFenceValue});
|
||||||
++pagingFenceRequestsCount;
|
|
||||||
condVar.notify_one();
|
condVar.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DirectSubmissionController::drainPagingFenceQueue() {
|
void DirectSubmissionController::drainPagingFenceQueue() {
|
||||||
std::lock_guard lock(condVarMutex);
|
std::lock_guard lock(this->condVarMutex);
|
||||||
|
|
||||||
while (!pagingFenceRequests.empty()) {
|
while (!pagingFenceRequests.empty()) {
|
||||||
auto request = pagingFenceRequests.front();
|
auto request = pagingFenceRequests.front();
|
||||||
pagingFenceRequests.pop();
|
pagingFenceRequests.pop();
|
||||||
--pagingFenceRequestsCount;
|
|
||||||
request.csr->unblockPagingFenceSemaphore(request.pagingFenceValue);
|
request.csr->unblockPagingFenceSemaphore(request.pagingFenceValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -330,7 +298,6 @@ void DirectSubmissionController::handlePagingFenceRequests(std::unique_lock<std:
|
|||||||
while (!pagingFenceRequests.empty()) {
|
while (!pagingFenceRequests.empty()) {
|
||||||
auto request = pagingFenceRequests.front();
|
auto request = pagingFenceRequests.front();
|
||||||
pagingFenceRequests.pop();
|
pagingFenceRequests.pop();
|
||||||
--pagingFenceRequestsCount;
|
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
|
|
||||||
request.csr->unblockPagingFenceSemaphore(request.pagingFenceValue);
|
request.csr->unblockPagingFenceSemaphore(request.pagingFenceValue);
|
||||||
|
|||||||
@@ -68,7 +68,6 @@ class DirectSubmissionController {
|
|||||||
|
|
||||||
void enqueueWaitForPagingFence(CommandStreamReceiver *csr, uint64_t pagingFenceValue);
|
void enqueueWaitForPagingFence(CommandStreamReceiver *csr, uint64_t pagingFenceValue);
|
||||||
void drainPagingFenceQueue();
|
void drainPagingFenceQueue();
|
||||||
void notifyNewSubmission();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct DirectSubmissionState {
|
struct DirectSubmissionState {
|
||||||
@@ -96,12 +95,10 @@ class DirectSubmissionController {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static void *controlDirectSubmissionsState(void *self);
|
static void *controlDirectSubmissionsState(void *self);
|
||||||
MOCKABLE_VIRTUAL void checkNewSubmissions();
|
void checkNewSubmissions();
|
||||||
bool isDirectSubmissionIdle(CommandStreamReceiver *csr, std::unique_lock<std::recursive_mutex> &csrLock);
|
bool isDirectSubmissionIdle(CommandStreamReceiver *csr, std::unique_lock<std::recursive_mutex> &csrLock);
|
||||||
bool isCopyEngineOnDeviceIdle(uint32_t rootDeviceIndex, std::optional<TaskCountType> &bcsTaskCount);
|
bool isCopyEngineOnDeviceIdle(uint32_t rootDeviceIndex, std::optional<TaskCountType> &bcsTaskCount);
|
||||||
bool hasNoWork();
|
|
||||||
MOCKABLE_VIRTUAL bool sleep(std::unique_lock<std::mutex> &lock);
|
MOCKABLE_VIRTUAL bool sleep(std::unique_lock<std::mutex> &lock);
|
||||||
MOCKABLE_VIRTUAL void wait(std::unique_lock<std::mutex> &lock) { condVar.wait(lock); }
|
|
||||||
MOCKABLE_VIRTUAL SteadyClock::time_point getCpuTimestamp();
|
MOCKABLE_VIRTUAL SteadyClock::time_point getCpuTimestamp();
|
||||||
MOCKABLE_VIRTUAL void overrideDirectSubmissionTimeouts(const ProductHelper &productHelper);
|
MOCKABLE_VIRTUAL void overrideDirectSubmissionTimeouts(const ProductHelper &productHelper);
|
||||||
|
|
||||||
@@ -110,7 +107,7 @@ class DirectSubmissionController {
|
|||||||
void updateLastSubmittedThrottle(QueueThrottle throttle);
|
void updateLastSubmittedThrottle(QueueThrottle throttle);
|
||||||
size_t getTimeoutParamsMapKey(QueueThrottle throttle, bool acLineStatus);
|
size_t getTimeoutParamsMapKey(QueueThrottle throttle, bool acLineStatus);
|
||||||
|
|
||||||
MOCKABLE_VIRTUAL void handlePagingFenceRequests(std::unique_lock<std::mutex> &lock, bool checkForNewSubmissions);
|
void handlePagingFenceRequests(std::unique_lock<std::mutex> &lock, bool checkForNewSubmissions);
|
||||||
MOCKABLE_VIRTUAL TimeoutElapsedMode timeoutElapsed();
|
MOCKABLE_VIRTUAL TimeoutElapsedMode timeoutElapsed();
|
||||||
std::chrono::microseconds getSleepValue() const { return std::chrono::microseconds(this->timeout / this->bcsTimeoutDivisor); }
|
std::chrono::microseconds getSleepValue() const { return std::chrono::microseconds(this->timeout / this->bcsTimeoutDivisor); }
|
||||||
|
|
||||||
@@ -136,8 +133,6 @@ class DirectSubmissionController {
|
|||||||
|
|
||||||
std::condition_variable condVar;
|
std::condition_variable condVar;
|
||||||
std::mutex condVarMutex;
|
std::mutex condVarMutex;
|
||||||
std::atomic_uint activeSubmissionsCount = 0;
|
|
||||||
std::atomic_uint pagingFenceRequestsCount = 0;
|
|
||||||
|
|
||||||
std::queue<WaitForPagingFenceRequest> pagingFenceRequests;
|
std::queue<WaitForPagingFenceRequest> pagingFenceRequests;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
#include "shared/source/command_stream/submissions_aggregator.h"
|
#include "shared/source/command_stream/submissions_aggregator.h"
|
||||||
#include "shared/source/debug_settings/debug_settings_manager.h"
|
#include "shared/source/debug_settings/debug_settings_manager.h"
|
||||||
#include "shared/source/device/device.h"
|
#include "shared/source/device/device.h"
|
||||||
#include "shared/source/direct_submission/direct_submission_controller.h"
|
|
||||||
#include "shared/source/direct_submission/direct_submission_hw.h"
|
#include "shared/source/direct_submission/direct_submission_hw.h"
|
||||||
#include "shared/source/direct_submission/relaxed_ordering_helper.h"
|
#include "shared/source/direct_submission/relaxed_ordering_helper.h"
|
||||||
#include "shared/source/execution_environment/execution_environment.h"
|
#include "shared/source/execution_environment/execution_environment.h"
|
||||||
@@ -589,9 +588,6 @@ template <typename GfxFamily, typename Dispatcher>
|
|||||||
bool DirectSubmissionHw<GfxFamily, Dispatcher>::submitCommandBufferToGpu(bool needStart, uint64_t gpuAddress, size_t size, bool needWait, const ResidencyContainer *allocationsForResidency) {
|
bool DirectSubmissionHw<GfxFamily, Dispatcher>::submitCommandBufferToGpu(bool needStart, uint64_t gpuAddress, size_t size, bool needWait, const ResidencyContainer *allocationsForResidency) {
|
||||||
if (needStart) {
|
if (needStart) {
|
||||||
this->ringStart = this->submit(gpuAddress, size, allocationsForResidency);
|
this->ringStart = this->submit(gpuAddress, size, allocationsForResidency);
|
||||||
if (auto controller = rootDeviceEnvironment.executionEnvironment.directSubmissionController.get()) {
|
|
||||||
controller->notifyNewSubmission();
|
|
||||||
}
|
|
||||||
return this->ringStart;
|
return this->ringStart;
|
||||||
} else {
|
} else {
|
||||||
if (needWait) {
|
if (needWait) {
|
||||||
|
|||||||
@@ -17,4 +17,4 @@ bool DirectSubmissionController::sleep(std::unique_lock<std::mutex> &lock) {
|
|||||||
void DirectSubmissionController::overrideDirectSubmissionTimeouts(const ProductHelper &productHelper) {
|
void DirectSubmissionController::overrideDirectSubmissionTimeouts(const ProductHelper &productHelper) {
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace NEO
|
} // namespace NEO
|
||||||
@@ -28,4 +28,4 @@ void DirectSubmissionController::overrideDirectSubmissionTimeouts(const ProductH
|
|||||||
this->maxTimeout = std::chrono::microseconds(maxTimeoutUs);
|
this->maxTimeout = std::chrono::microseconds(maxTimeoutUs);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace NEO
|
} // namespace NEO
|
||||||
@@ -67,7 +67,7 @@ bool SVMAllocsManager::SvmAllocationCache::insert(size_t size, void *ptr, SvmAll
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_lock<std::mutex> lock(this->mtx);
|
std::lock_guard<std::mutex> lock(this->mtx);
|
||||||
if (svmData->device ? svmData->device->shouldLimitAllocationsReuse() : memoryManager->shouldLimitAllocationsReuse()) {
|
if (svmData->device ? svmData->device->shouldLimitAllocationsReuse() : memoryManager->shouldLimitAllocationsReuse()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -107,12 +107,6 @@ bool SVMAllocsManager::SvmAllocationCache::insert(size_t size, void *ptr, SvmAll
|
|||||||
.operationType = CacheOperationType::insert,
|
.operationType = CacheOperationType::insert,
|
||||||
.isSuccess = isSuccess});
|
.isSuccess = isSuccess});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto usmReuseCleaner = this->memoryManager->peekExecutionEnvironment().unifiedMemoryReuseCleaner.get()) {
|
|
||||||
lock.unlock();
|
|
||||||
usmReuseCleaner->notifySvmAllocationsCacheUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
return isSuccess;
|
return isSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -208,7 +208,6 @@ class SVMAllocsManager {
|
|||||||
static bool allocUtilizationAllows(size_t requestedSize, size_t reuseCandidateSize);
|
static bool allocUtilizationAllows(size_t requestedSize, size_t reuseCandidateSize);
|
||||||
static bool alignmentAllows(void *ptr, size_t alignment);
|
static bool alignmentAllows(void *ptr, size_t alignment);
|
||||||
bool isInUse(SvmCacheAllocationInfo &cacheAllocInfo);
|
bool isInUse(SvmCacheAllocationInfo &cacheAllocInfo);
|
||||||
bool isEmpty() { return allocations.empty(); }
|
|
||||||
void *get(size_t size, const UnifiedMemoryProperties &unifiedMemoryProperties);
|
void *get(size_t size, const UnifiedMemoryProperties &unifiedMemoryProperties);
|
||||||
void trim();
|
void trim();
|
||||||
void trimOldAllocs(std::chrono::high_resolution_clock::time_point trimTimePoint, bool trimAll);
|
void trimOldAllocs(std::chrono::high_resolution_clock::time_point trimTimePoint, bool trimAll);
|
||||||
|
|||||||
@@ -25,10 +25,6 @@ UnifiedMemoryReuseCleaner::~UnifiedMemoryReuseCleaner() {
|
|||||||
void UnifiedMemoryReuseCleaner::stopThread() {
|
void UnifiedMemoryReuseCleaner::stopThread() {
|
||||||
keepCleaning.store(false);
|
keepCleaning.store(false);
|
||||||
runCleaning.store(false);
|
runCleaning.store(false);
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(condVarMutex);
|
|
||||||
condVar.notify_one();
|
|
||||||
}
|
|
||||||
if (unifiedMemoryReuseCleanerThread) {
|
if (unifiedMemoryReuseCleanerThread) {
|
||||||
unifiedMemoryReuseCleanerThread->join();
|
unifiedMemoryReuseCleanerThread->join();
|
||||||
unifiedMemoryReuseCleanerThread.reset();
|
unifiedMemoryReuseCleanerThread.reset();
|
||||||
@@ -48,22 +44,11 @@ void *UnifiedMemoryReuseCleaner::cleanUnifiedMemoryReuse(void *self) {
|
|||||||
if (!cleaner->keepCleaning.load()) {
|
if (!cleaner->keepCleaning.load()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_lock lock(cleaner->condVarMutex);
|
|
||||||
while (cleaner->keepCleaning.load() && cleaner->isEmpty()) {
|
|
||||||
cleaner->wait(lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
NEO::sleep(sleepTime);
|
NEO::sleep(sleepTime);
|
||||||
cleaner->trimOldInCaches();
|
cleaner->trimOldInCaches();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnifiedMemoryReuseCleaner::notifySvmAllocationsCacheUpdate() {
|
|
||||||
std::lock_guard<std::mutex> lock(condVarMutex);
|
|
||||||
condVar.notify_one();
|
|
||||||
}
|
|
||||||
|
|
||||||
void UnifiedMemoryReuseCleaner::registerSvmAllocationCache(SvmAllocationCache *cache) {
|
void UnifiedMemoryReuseCleaner::registerSvmAllocationCache(SvmAllocationCache *cache) {
|
||||||
std::lock_guard<std::mutex> lockSvmAllocationCaches(this->svmAllocationCachesMutex);
|
std::lock_guard<std::mutex> lockSvmAllocationCaches(this->svmAllocationCachesMutex);
|
||||||
this->svmAllocationCaches.push_back(cache);
|
this->svmAllocationCaches.push_back(cache);
|
||||||
@@ -98,4 +83,4 @@ void UnifiedMemoryReuseCleaner::startThread() {
|
|||||||
this->unifiedMemoryReuseCleanerThread = Thread::createFunc(cleanUnifiedMemoryReuse, reinterpret_cast<void *>(this));
|
this->unifiedMemoryReuseCleanerThread = Thread::createFunc(cleanUnifiedMemoryReuse, reinterpret_cast<void *>(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace NEO
|
} // namespace NEO
|
||||||
@@ -11,7 +11,6 @@
|
|||||||
#include "shared/source/memory_manager/unified_memory_manager.h"
|
#include "shared/source/memory_manager/unified_memory_manager.h"
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <condition_variable>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -34,12 +33,6 @@ class UnifiedMemoryReuseCleaner : NEO::NonCopyableAndNonMovableClass {
|
|||||||
|
|
||||||
void registerSvmAllocationCache(SvmAllocationCache *cache);
|
void registerSvmAllocationCache(SvmAllocationCache *cache);
|
||||||
void unregisterSvmAllocationCache(SvmAllocationCache *cache);
|
void unregisterSvmAllocationCache(SvmAllocationCache *cache);
|
||||||
MOCKABLE_VIRTUAL void wait(std::unique_lock<std::mutex> &lock) { condVar.wait(lock); }
|
|
||||||
MOCKABLE_VIRTUAL bool isEmpty() {
|
|
||||||
std::unique_lock<std::mutex> lock(svmAllocationCachesMutex);
|
|
||||||
return std::all_of(svmAllocationCaches.begin(), svmAllocationCaches.end(), [](const auto &it) { return it->isEmpty(); });
|
|
||||||
}
|
|
||||||
void notifySvmAllocationsCacheUpdate();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void startCleaning() { runCleaning.store(true); };
|
void startCleaning() { runCleaning.store(true); };
|
||||||
@@ -50,9 +43,6 @@ class UnifiedMemoryReuseCleaner : NEO::NonCopyableAndNonMovableClass {
|
|||||||
std::vector<SvmAllocationCache *> svmAllocationCaches;
|
std::vector<SvmAllocationCache *> svmAllocationCaches;
|
||||||
std::mutex svmAllocationCachesMutex;
|
std::mutex svmAllocationCachesMutex;
|
||||||
|
|
||||||
std::mutex condVarMutex;
|
|
||||||
std::condition_variable condVar;
|
|
||||||
|
|
||||||
std::atomic_bool runCleaning = false;
|
std::atomic_bool runCleaning = false;
|
||||||
std::atomic_bool keepCleaning = true;
|
std::atomic_bool keepCleaning = true;
|
||||||
|
|
||||||
|
|||||||
@@ -20,8 +20,6 @@ struct MockUnifiedMemoryReuseCleaner : public UnifiedMemoryReuseCleaner {
|
|||||||
trimOldInCachesCalled = true;
|
trimOldInCachesCalled = true;
|
||||||
if (callBaseTrimOldInCaches) {
|
if (callBaseTrimOldInCaches) {
|
||||||
UnifiedMemoryReuseCleaner::trimOldInCaches();
|
UnifiedMemoryReuseCleaner::trimOldInCaches();
|
||||||
} else {
|
|
||||||
clearCaches();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void startThread() override {
|
void startThread() override {
|
||||||
@@ -29,17 +27,8 @@ struct MockUnifiedMemoryReuseCleaner : public UnifiedMemoryReuseCleaner {
|
|||||||
UnifiedMemoryReuseCleaner::startThread();
|
UnifiedMemoryReuseCleaner::startThread();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
void wait(std::unique_lock<std::mutex> &lock) override {
|
bool trimOldInCachesCalled = false;
|
||||||
waitOnConditionVar.store(true);
|
|
||||||
UnifiedMemoryReuseCleaner::wait(lock);
|
|
||||||
};
|
|
||||||
void clearCaches() {
|
|
||||||
std::lock_guard<std::mutex> lock(svmAllocationCachesMutex);
|
|
||||||
svmAllocationCaches.clear();
|
|
||||||
}
|
|
||||||
std::atomic_bool trimOldInCachesCalled = false;
|
|
||||||
std::atomic_bool waitOnConditionVar = false;
|
|
||||||
bool callBaseStartThread = false;
|
bool callBaseStartThread = false;
|
||||||
bool callBaseTrimOldInCaches = true;
|
bool callBaseTrimOldInCaches = true;
|
||||||
};
|
};
|
||||||
} // namespace NEO
|
} // namespace NEO
|
||||||
@@ -42,21 +42,6 @@ struct DirectSubmissionControllerMock : public DirectSubmissionController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void wait(std::unique_lock<std::mutex> &lock) override {
|
|
||||||
waitOnConditionVar.store(true);
|
|
||||||
DirectSubmissionController::wait(lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
void handlePagingFenceRequests(std::unique_lock<std::mutex> &lock, bool checkForNewSubmissions) override {
|
|
||||||
handlePagingFenceRequestsCalled.store(true);
|
|
||||||
DirectSubmissionController::handlePagingFenceRequests(lock, checkForNewSubmissions);
|
|
||||||
}
|
|
||||||
|
|
||||||
void checkNewSubmissions() override {
|
|
||||||
checkNewSubmissionCalled.store(true);
|
|
||||||
DirectSubmissionController::checkNewSubmissions();
|
|
||||||
}
|
|
||||||
|
|
||||||
SteadyClock::time_point getCpuTimestamp() override {
|
SteadyClock::time_point getCpuTimestamp() override {
|
||||||
return cpuTimestamp;
|
return cpuTimestamp;
|
||||||
}
|
}
|
||||||
@@ -74,9 +59,6 @@ struct DirectSubmissionControllerMock : public DirectSubmissionController {
|
|||||||
std::atomic<bool> sleepReturnValue{false};
|
std::atomic<bool> sleepReturnValue{false};
|
||||||
std::atomic<TimeoutElapsedMode> timeoutElapsedReturnValue{TimeoutElapsedMode::notElapsed};
|
std::atomic<TimeoutElapsedMode> timeoutElapsedReturnValue{TimeoutElapsedMode::notElapsed};
|
||||||
std::atomic<bool> timeoutElapsedCallBase{false};
|
std::atomic<bool> timeoutElapsedCallBase{false};
|
||||||
std::atomic<bool> waitOnConditionVar{false};
|
|
||||||
std::atomic<bool> checkNewSubmissionCalled{false};
|
|
||||||
std::atomic<bool> handlePagingFenceRequestsCalled{false};
|
|
||||||
bool callBaseSleepMethod = false;
|
bool callBaseSleepMethod = false;
|
||||||
};
|
};
|
||||||
} // namespace NEO
|
} // namespace NEO
|
||||||
Reference in New Issue
Block a user