สนับสนุนการพัฒนาของ Enkits ผ่านผู้สนับสนุน GitHub หรือ Patreon

ตัวกำหนดตารางเวลางาน C และ C ++ ที่ได้รับอนุญาตสำหรับการสร้างโปรแกรมแบบขนาน ต้องการการสนับสนุน C ++ 11
เป้าหมายหลักของ enkits คือการช่วยให้นักพัฒนาสร้างโปรแกรมที่จัดการทั้งข้อมูลและระดับความเท่าเทียมกันในระดับงานเพื่อใช้ประสิทธิภาพเต็มรูปแบบของซีพียูมัลติคอร์ในขณะที่มีน้ำหนักเบา (มีรหัสเพียงเล็กน้อย) และใช้งานง่าย
Enkits ได้รับการพัฒนาและใช้ใน Avoyd Codebase ของ Enkisoftware
Enkits ได้รับการพัฒนาเป็นหลักในสถาปัตยกรรม X64 และ X86 Intel บน MS Windows พร้อมการสนับสนุนที่ดีสำหรับ Linux และการสนับสนุนที่ผ่านการทดสอบบ่อยครั้งบน Mac OS และ ARM Android
มีหลายตัวอย่างในโฟลเดอร์ตัวอย่าง
สำหรับตัวอย่างเพิ่มเติมดูที่ https://github.com/dougbinks/enkitsexamples
การสร้าง Enkits นั้นง่ายเพียงเพิ่มไฟล์ใน Enkits/SRC ในระบบบิลด์ของคุณ (_c.* ไฟล์สามารถถูกละเว้นได้หากคุณต้องการอินเตอร์เฟส C ++ เท่านั้น) และเพิ่ม Enkits/SRC ลงในเส้นทางรวมของคุณ การสร้าง UNIX / LINUX อาจต้องใช้ไลบรารี PTHREADS
สำหรับ C ++
#include "TaskScheduler.h"TaskScheduler.cppสำหรับ C
#include "TaskScheduler_c.h"TaskScheduler.cppTaskScheduler_c.cppสำหรับ CMake บน Windows / Mac OS X / Linux ที่ติดตั้ง CMake เปิดให้บริการในไดเรกทอรี Enkits และ::
mkdir buildcd buildcmake ..make all หรือสำหรับ Visual Studio Open enkiTS.sln ฉันขอแนะนำให้ใช้ enkits โดยตรงจากแหล่งที่มาในแต่ละโครงการแทนที่จะติดตั้งเพื่อใช้งานระบบกว้าง อย่างไรก็ตามสคริปต์ cmake ของ Enkits สามารถใช้ในการติดตั้งไลบรารีได้หากตัวแปร cmake ENKITS_INSTALL ถูกตั้งค่าเป็น ON (ค่าเริ่มต้นเป็น OFF )
เมื่อติดตั้งไฟล์ส่วนหัวจะถูกติดตั้งในไดเรกทอรีย่อยของเส้นทางรวม 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 ได้เลิกใช้แล้วเนื่องจากฉันไม่ทราบว่ามีใครต้องการ
รุ่นเธรดผู้ใช้จะไม่ได้รับการดูแลอีกต่อไปเนื่องจากไม่ได้ใช้งานอีกต่อไป ฟังก์ชั่นที่คล้ายกันสามารถรับได้ด้วย externaltaskthreads
Avoyd เป็นเกม Freedom Voxel ที่เป็นนามธรรม 6 องศา Enkits ได้รับการพัฒนาเพื่อใช้ใน Avoyd เครื่องยนต์ภายในของเรา

เครื่องกำเนิดพื้นผิว GPU/CPU
รหัส Aras Pranckevičius 'สำหรับซีรี่ส์ของเขาในการทดลอง Daily Path Tracer ด้วยภาษาต่างๆ
-
Marco Castorina และหนังสือของ Gabriel Sassone เกี่ยวกับการพัฒนากลไกการเรนเดอร์ที่ทันสมัยจากหลักการแรกโดยใช้ Vulkan API Enkits ใช้เป็นไลบรารีงานเพื่อแจกจ่ายงานข้ามแกน
ลิขสิทธิ์ (c) 2013-2020 Doug Binks
ซอฟต์แวร์นี้มีให้ 'เป็น' โดยไม่มีการรับประกันโดยชัดแจ้งหรือโดยนัย ไม่ว่าในกรณีใดผู้เขียนจะต้องรับผิดชอบต่อความเสียหายใด ๆ ที่เกิดขึ้นจากการใช้ซอฟต์แวร์นี้
ได้รับอนุญาตให้ทุกคนใช้ซอฟต์แวร์นี้เพื่อวัตถุประสงค์ใด ๆ รวมถึงแอปพลิเคชันเชิงพาณิชย์และเพื่อแก้ไขและแจกจ่ายซ้ำได้อย่างอิสระภายใต้ข้อ จำกัด ดังต่อไปนี้: