通過GitHub贊助商或Patreon來支持Enkits的開發

用於創建並行程序的允許許可的C和C ++任務調度程序。需要C ++ 11支持。
ENKIT的主要目標是幫助開發人員創建處理數據和任務級別並行性的程序,以利用多核CPU的全部性能,同時輕巧(僅少量代碼)且易於使用。
Enkits是為Enkisoftware的Avoyd Codebase開發的。
Enkits主要是在MS Windows上的X64和X86 Intel架構上開發的,對Linux的測試支持進行了經過良好測試,並且在Mac OS和ARM Android上進行了較少測試的支持。
示例文件夾中存在幾個示例。
有關進一步的示例,請參見https://github.com/dougbinks/enkitsexamples
構建enkit很簡單,只需將enkit/src中的文件添加到您的構建系統(_C。*如果您只需要C ++接口,就可以忽略文件),然後將enkits/src添加到您的INCLUCE路徑。 UNIX / Linux構建可能需要Pthreads庫。
對於C ++
#include "TaskScheduler.h"TaskScheduler.cpp對於c
#include "TaskScheduler_c.h"TaskScheduler.cppTaskScheduler_c.cpp對於Cmake,在安裝CMAKE的Windows / Mac OS X / Linux上,在Enkits目錄中打開一個提示
mkdir buildcd buildcmake ..make all或用於Visual Studio Open enkiTS.sln 我建議直接在每個項目中直接使用Enkits,而不是將其安裝以進行系統大量使用。但是,如果ENKITS_INSTALL cmake變量設置為ON (默認為OFF ),則ENKITS的CMAKE腳本也可用於安裝庫。
安裝後,將標頭文件安裝在Include路徑的子目錄中, include/enkiTS以確保它們不會與其他軟件包中的標頭文件衝突。當構建應用程序確保這是INCLUDE_PATH變量的一部分時,或者確保Enkits在源文件中的標頭路徑中,例如使用#include "enkiTS/TaskScheduler.h" ,而不是#include "TaskScheduler.h" 。
#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 ;
}C ++ 98兼容分支已被棄用,因為我不知道有人需要它。
用戶線程版本不再使用,因為它們不再使用。可以使用外部詞法讀物獲得類似的功能
Avoyd是一種抽象的6度自由度Voxel遊戲。 Enkits是開髮用於我們的內部發動機供電Avoyd的。

GPU/CPU紋理髮生器
ArasPranckevičius的代碼在每日路徑示踪劑上使用各種語言進行實驗。
。
Marco Castorina和Gabriel Sassone的書關於使用Vulkan API從第一原理開發現代渲染引擎的書。 Enkits用作任務庫來跨內核分發工作。
版權(C)2013-2020 Doug Binks
該軟件提供了“原樣”,而無需任何明示或暗示的保證。在任何情況下,作者都不應對使用此軟件造成的任何損害負責。
授予任何人,包括任何目的,包括商業應用程序,並將其更改並自由地重新分配,但要予以自由限制: