mirror of
https://github.com/mmueller41/mxtasking.git
synced 2026-01-21 12:42:57 +01:00
first tests for work stealing
This commit is contained in:
@@ -140,6 +140,16 @@ public:
|
|||||||
|
|
||||||
std::uint8_t numa_node_id() { return _numa_node_id; }
|
std::uint8_t numa_node_id() { return _numa_node_id; }
|
||||||
|
|
||||||
|
TaskInterface* steal_task() noexcept {
|
||||||
|
if (!_local_queues[mx::tasking::priority::normal].empty()) {
|
||||||
|
return _local_queues[mx::tasking::priority::normal].pop_front();
|
||||||
|
}
|
||||||
|
else if (!_local_queues[mx::tasking::priority::low].empty()) {
|
||||||
|
return _local_queues[mx::tasking::priority::low].pop_front();
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Backend queues for multiple produces in different NUMA regions and different priorities,
|
// Backend queues for multiple produces in different NUMA regions and different priorities,
|
||||||
alignas(64)
|
alignas(64)
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ Scheduler::Scheduler(const mx::util::core_set &core_set, const std::uint16_t pre
|
|||||||
Worker(worker_id, core_id, this->_channel_numa_node_map[worker_id], this->_is_running,
|
Worker(worker_id, core_id, this->_channel_numa_node_map[worker_id], this->_is_running,
|
||||||
prefetch_distance, this->_epoch_manager[worker_id], this->_epoch_manager.global_epoch(),
|
prefetch_distance, this->_epoch_manager[worker_id], this->_epoch_manager.global_epoch(),
|
||||||
this->_statistic);
|
this->_statistic);
|
||||||
|
this->_worker[worker_id]->setScheduler(this);
|
||||||
|
allWorkers.push_back(this->_worker[worker_id]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include <mx/util/core_set.h>
|
#include <mx/util/core_set.h>
|
||||||
#include <mx/util/random.h>
|
#include <mx/util/random.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
namespace mx::tasking {
|
namespace mx::tasking {
|
||||||
/**
|
/**
|
||||||
@@ -171,6 +172,16 @@ public:
|
|||||||
|
|
||||||
bool operator!=(const util::core_set &cores) const noexcept { return _core_set != cores; }
|
bool operator!=(const util::core_set &cores) const noexcept { return _core_set != cores; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return allWorkers
|
||||||
|
*/
|
||||||
|
std::vector<Worker *>& getAllWorkers() noexcept { return allWorkers; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return allWorkersMutex
|
||||||
|
*/
|
||||||
|
std::mutex& getAllWorkersMutex() noexcept { return allWorkersMutex; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Cores to run the worker threads on.
|
// Cores to run the worker threads on.
|
||||||
const util::core_set _core_set;
|
const util::core_set _core_set;
|
||||||
@@ -197,6 +208,12 @@ private:
|
|||||||
// Profiler for idle times.
|
// Profiler for idle times.
|
||||||
profiling::Profiler _profiler{};
|
profiling::Profiler _profiler{};
|
||||||
|
|
||||||
|
// All initialized workers.
|
||||||
|
std::vector<Worker *> allWorkers;
|
||||||
|
|
||||||
|
// Mutex for the worker vector.
|
||||||
|
std::mutex allWorkersMutex;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make a decision whether a task should be scheduled to the local
|
* Make a decision whether a task should be scheduled to the local
|
||||||
* channel or a remote.
|
* channel or a remote.
|
||||||
|
|||||||
@@ -131,6 +131,30 @@ void Worker::execute()
|
|||||||
runtime::delete_task(core_id, task);
|
runtime::delete_task(core_id, task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
stealTasks();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Worker::stealTasks(){
|
||||||
|
std::cout << "stealTasks" << std::endl;
|
||||||
|
// This assumes that the worker has access to the other workers through
|
||||||
|
// a data structure named "allWorkers". You will need to adjust this
|
||||||
|
// based on your program's structure.
|
||||||
|
std::lock_guard<std::mutex> lock(_scheduler->getAllWorkersMutex());
|
||||||
|
for (auto& worker : _scheduler->getAllWorkers())
|
||||||
|
{
|
||||||
|
if (worker == this)
|
||||||
|
{
|
||||||
|
continue; // Skip the current worker.
|
||||||
|
}
|
||||||
|
|
||||||
|
TaskInterface* stolenTask = worker->_channel.steal_task();
|
||||||
|
if (stolenTask != nullptr)
|
||||||
|
{
|
||||||
|
// If the stolen task is not null, push it to the current worker's channel
|
||||||
|
this->_channel.push_back_local(stolenTask);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,9 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace mx::tasking {
|
namespace mx::tasking {
|
||||||
|
|
||||||
|
class Scheduler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The worker executes tasks from his own channel, until the "running" flag is false.
|
* The worker executes tasks from his own channel, until the "running" flag is false.
|
||||||
*/
|
*/
|
||||||
@@ -40,6 +43,8 @@ public:
|
|||||||
[[nodiscard]] Channel &channel() noexcept { return _channel; }
|
[[nodiscard]] Channel &channel() noexcept { return _channel; }
|
||||||
[[nodiscard]] const Channel &channel() const noexcept { return _channel; }
|
[[nodiscard]] const Channel &channel() const noexcept { return _channel; }
|
||||||
|
|
||||||
|
void setScheduler(Scheduler* scheduler) { _scheduler = scheduler; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Id of the logical core.
|
// Id of the logical core.
|
||||||
const std::uint16_t _target_core_id;
|
const std::uint16_t _target_core_id;
|
||||||
@@ -68,6 +73,9 @@ private:
|
|||||||
// Flag for "running" state of MxTasking.
|
// Flag for "running" state of MxTasking.
|
||||||
const util::maybe_atomic<bool> &_is_running;
|
const util::maybe_atomic<bool> &_is_running;
|
||||||
|
|
||||||
|
// Scheduler
|
||||||
|
Scheduler* _scheduler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Analyzes the given task and chooses the execution method regarding synchronization.
|
* Analyzes the given task and chooses the execution method regarding synchronization.
|
||||||
* @param task Task to be executed.
|
* @param task Task to be executed.
|
||||||
@@ -126,5 +134,8 @@ private:
|
|||||||
*/
|
*/
|
||||||
TaskResult execute_optimistic_read(std::uint16_t core_id, std::uint16_t channel_id,
|
TaskResult execute_optimistic_read(std::uint16_t core_id, std::uint16_t channel_id,
|
||||||
resource::ResourceInterface *resource, TaskInterface *task);
|
resource::ResourceInterface *resource, TaskInterface *task);
|
||||||
|
|
||||||
|
void stealTasks();
|
||||||
|
|
||||||
};
|
};
|
||||||
} // namespace mx::tasking
|
} // namespace mx::tasking
|
||||||
Reference in New Issue
Block a user