Unterstützen Sie die Entwicklung von Enkits durch Github -Sponsoren oder Patreon

Ein zulässig lizenzierter C- und C ++ - Task Scheduler zum Erstellen paralleler Programme. Benötigt C ++ 11 Unterstützung.
Das Hauptziel von Enkits ist es, Entwicklern dabei zu helfen, Programme zu erstellen, die sowohl die Daten als auch die Aufgabenebene parallelist machen, um die volle Leistung von Multicore -CPUs zu nutzen, während sie leicht (nur eine kleine Menge Code) und einfach zu verwenden sind.
Enkits wurde für Avoyd Codebase von Enkisoftware entwickelt und wird verwendet.
Enkits wird hauptsächlich auf X64- und X86 -Intel -Architekturen unter MS Windows entwickelt, wobei gut getestete Unterstützung für Linux und etwas seltener testeter Unterstützung unter Mac OS und ARM Android ist.
Im Beispielordner gibt es mehrere Beispiele.
Weitere Beispiele finden Sie unter https://github.com/dougbinks/enkitsexamples
Das Erstellen von Enkits ist einfach. Fügen Sie einfach die Dateien in Enkits/SRC zu Ihrem Build -System hinzu (_c.* Dateien können ignoriert werden, wenn Sie nur eine C ++ - Schnittstelle benötigen) und fügen Sie Ihrem Pfad Enkits/SRC hinzu. Unix / Linux -Builds erfordern wahrscheinlich die PThreads -Bibliothek.
Für c ++
#include "TaskScheduler.h"TaskScheduler.cppFür c
#include "TaskScheduler_c.h"TaskScheduler.cppTaskScheduler_c.cppFür CMAKE unter Windows / Mac OS X / Linux mit installiertem CMAKE öffnen Sie eine Eingabeaufforderung im Verzeichnis von Enkits und:
mkdir buildcd buildcmake ..make all oder für visual Studio Open enkiTS.sln Ich empfehle, Enkits direkt aus der Quelle in jedem Projekt zu verwenden, anstatt es für die systemweite Verwendung zu installieren. Das CMAKE -Skript von Enkits kann jedoch auch zur Installation der Bibliothek verwendet werden, wenn die CMake -Variable ENKITS_INSTALL auf ON festgelegt ist (es ist standardmäßig OFF ).
Bei der Installation werden die Header -Dateien in einem Unterverzeichnis des Include -Pfades include/enkiTS installiert, um sicherzustellen, dass sie nicht mit Header -Dateien aus anderen Paketen in Konflikt stehen. Wenn Sie Anwendungen erstellen #include "TaskScheduler.h" stellen Sie entweder sicher #include "enkiTS/TaskScheduler.h" dass dies Teil der Variablen INCLUDE_PATH ist oder sicherstellen, dass sich Enkits im Header -Pfad in den Quelldateien befinden.
#include "TaskScheduler.h"
enki:: TaskScheduler g_TS ;
// define a task set, can ignore range if we only do one thing
struct ParallelTaskSet : enki :: ITaskSet {
void ExecuteRange ( enki :: TaskSetPartition range_ , uint32_t threadnum_ ) override {
// do something here, can issue tasks with g_TS
}
};
int main ( int argc , const char * argv []) {
g_TS . Initialize ();
ParallelTaskSet task ; // default constructor has a set size of 1
g_TS . AddTaskSetToPipe ( & task );
// wait for task set (running tasks if they exist)
// since we've just added it and it has no range we'll likely run it.
g_TS . WaitforTask ( & task );
return 0 ;
} #include "TaskScheduler.h"
enki:: TaskScheduler g_TS ;
int main ( int argc , const char * argv []) {
g_TS . Initialize ();
enki:: TaskSet task ( 1 , []( enki :: TaskSetPartition range_ , uint32_t threadnum_ ) {
// do something here
} );
g_TS . AddTaskSetToPipe ( & task );
g_TS . WaitforTask ( & task );
return 0 ;
} // See full example in Priorities.cpp
#include "TaskScheduler.h"
enki:: TaskScheduler g_TS ;
struct ExampleTask : enki :: ITaskSet
{
ExampleTask ( ) { m_SetSize = size_ ; }
void ExecuteRange ( enki :: TaskSetPartition range_ , uint32_t threadnum_ ) override {
// See full example in Priorities.cpp
}
};
// This example demonstrates how to run a long running task alongside tasks
// which must complete as early as possible using priorities.
int main ( int argc , const char * argv [])
{
g_TS . Initialize ();
ExampleTask lowPriorityTask ( 10 );
lowPriorityTask . m_Priority = enki :: TASK_PRIORITY_LOW ;
ExampleTask highPriorityTask ( 1 );
highPriorityTask . m_Priority = enki :: TASK_PRIORITY_HIGH ;
g_TS . AddTaskSetToPipe ( & lowPriorityTask );
for ( int task = 0 ; task < 10 ; ++ task )
{
// run high priority tasks
g_TS . AddTaskSetToPipe ( & highPriorityTask );
// wait for task but only run tasks of the same priority or higher on this thread
g_TS . WaitforTask ( & highPriorityTask , highPriorityTask . m_Priority );
}
// wait for low priority task, run any tasks on this thread whilst waiting
g_TS . WaitforTask ( & lowPriorityTask );
return 0 ;
} #include "TaskScheduler.h"
enki:: TaskScheduler g_TS ;
// define a task set, can ignore range if we only do one thing
struct PinnedTask : enki :: IPinnedTask {
void Execute () override {
// do something here, can issue tasks with g_TS
}
};
int main ( int argc , const char * argv []) {
g_TS . Initialize ();
PinnedTask task ; //default constructor sets thread for pinned task to 0 (main thread)
g_TS . AddPinnedTask ( & task );
// RunPinnedTasks must be called on main thread to run any pinned tasks for that thread.
// Tasking threads automatically do this in their task loop.
g_TS . RunPinnedTasks ();
// wait for task set (running tasks if they exist)
// since we've just added it and it has no range we'll likely run it.
g_TS . WaitforTask ( & task );
return 0 ;
} #include "TaskScheduler.h"
enki:: TaskScheduler g_TS ;
// define a task set, can ignore range if we only do one thing
struct TaskA : enki :: ITaskSet {
void ExecuteRange ( enki :: TaskSetPartition range_ , uint32_t threadnum_ ) override {
// do something here, can issue tasks with g_TS
}
};
struct TaskB : enki :: ITaskSet {
enki:: Dependency m_Dependency ;
void ExecuteRange ( enki :: TaskSetPartition range_ , uint32_t threadnum_ ) override {
// do something here, can issue tasks with g_TS
}
};
int main ( int argc , const char * argv []) {
g_TS . Initialize ();
// set dependencies once (can set more than one if needed).
TaskA taskA ;
TaskB taskB ;
taskB . SetDependency ( taskB . m_Dependency , & taskA );
g_TS . AddTaskSetToPipe ( & taskA ); // add first task
g_TS . WaitforTask ( & taskB ); // wait for last
return 0 ;
} #include "TaskScheduler.h"
enki:: TaskScheduler g_TS ;
struct ParallelTaskSet : ITaskSet
{
void ExecuteRange ( enki :: TaskSetPartition range_ , uint32_t threadnum_ ) override {
// Do something
}
};
void threadFunction ()
{
g_TS . RegisterExternalTaskThread ();
// sleep for a while instead of doing something such as file IO
std::this_thread::sleep_for( std ::chrono:: milliseconds ( num_ * 100 ) );
ParallelTaskSet task ;
g_TS . AddTaskSetToPipe ( & task );
g_TS . WaitforTask ( & task );
g_TS . DeRegisterExternalTaskThread ();
}
int main ( int argc , const char * argv [])
{
enki:: TaskSchedulerConfig config ;
config . numExternalTaskThreads = 1 ; // we have one extra external thread
g_TS . Initialize ( config );
std:: thread exampleThread ( threadFunction );
exampleThread . join ();
return 0 ;
}# include " TaskScheduler.h "
enki::TaskScheduler g_TS;
struct RunPinnedTaskLoopTask : enki::IPinnedTask
{
void Execute () override
{
while ( !g_TS. GetIsShutdownRequested () )
{
g_TS. WaitForNewPinnedTasks (); // this thread will 'sleep' until there are new pinned tasks
g_TS. RunPinnedTasks ();
}
}
};
struct PretendDoFileIO : enki::IPinnedTask
{
void Execute () override
{
// Do file IO
}
};
int main ( int argc, const char * argv[])
{
enki::TaskSchedulerConfig config;
// In this example we create more threads than the hardware can run,
// because the IO thread will spend most of it's time idle or blocked
// and therefore not scheduled for CPU time by the OS
config. numTaskThreadsToCreate += 1 ;
g_TS. Initialize ( config );
// in this example we place our IO threads at the end
RunPinnedTaskLoopTask runPinnedTaskLoopTasks;
runPinnedTaskLoopTasks. threadNum = g_TS. GetNumTaskThreads () - 1 ;
g_TS. AddPinnedTask ( &runPinnedTaskLoopTasks );
// Send pretend file IO task to external thread FILE_IO
PretendDoFileIO pretendDoFileIO;
pretendDoFileIO. threadNum = runPinnedTaskLoopTasks. threadNum ;
g_TS. AddPinnedTask ( &pretendDoFileIO );
// ensure runPinnedTaskLoopTasks complete by explicitly calling shutdown
g_TS. WaitforAllAndShutdown ();
return 0 ;
}Der C ++ 98 -kompatible Zweig wurde veraltet, da ich nicht bekannt ist, dass jemand ihn braucht.
Die Benutzer -Thread -Versionen werden nicht mehr aufrechterhalten, da sie nicht mehr verwendet werden. Eine ähnliche Funktionalität kann mit den exteraltaskthreads erhalten werden
Avoyd ist ein abstraktes 6 Grad of Freedom Voxel. Enkits wurde für den Einsatz in unserem internen Motor mit Avoyd entwickelt.

GPU/CPU -Texturgenerator
Der Code von Aras PranCkevičius für seine Serie über den täglichen Path -Tracer -Experimenten mit verschiedenen Sprachen.
.
Marco Castorina und Gabriel Sassones Buch über die Entwicklung einer modernen Rendering -Engine aus den ersten Prinzipien mit der Vulkan -API. Enkits wird als Aufgabenbibliothek verwendet, um Arbeiten über Kerne hinweg zu verteilen.
Copyright (C) 2013-2020 Doug Binks
Diese Software wird "As-is" ohne ausdrückliche oder implizite Garantie bereitgestellt. In keiner Veranstaltung haftet die Autoren für Schäden, die sich aus der Verwendung dieser Software ergeben.
Die Erlaubnis wird jedem erteilt, diese Software für jeden Zweck, einschließlich kommerzieller Anwendungen, zu verwenden und sie zu ändern und frei zu verteilen, vorbehaltlich der folgenden Einschränkungen: