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:
Compute-Runtime-Validation
2025-10-06 20:04:43 +02:00
committed by Compute-Runtime-Automation
parent ac296f76ba
commit bafb847c73
14 changed files with 43 additions and 242 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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;
} }

View File

@@ -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);

View File

@@ -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;
}; };

View File

@@ -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) {

View File

@@ -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

View File

@@ -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

View File

@@ -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;
} }

View File

@@ -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);

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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