دعم تطوير Enkits من خلال رعاة Github أو Patreon

جدولة مهام C و C ++ المرخصة لإنشاء برامج متوازية. يتطلب دعم C ++ 11.
الهدف الأساسي لـ Enkits هو مساعدة المطورين على إنشاء برامج تتعامل مع كل من البيانات ومستوى المهمة التوازي لاستخدام الأداء الكامل لحزب الواحدة الفوري متعدد الأزهار ، في حين أن الخفيفة الوزن (كمية صغيرة فقط من التعليمات البرمجية) وسهلة الاستخدام.
تم تطوير Enkits ، ويستخدم في قاعدة كود Avoyd من Enkisoftware.
تم تطوير Enkits في المقام الأول على بنية X64 و X86 Intel على Windows MS ، مع دعم تم اختباره جيدًا لـ 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 مباشرة من المصدر في كل مشروع بدلاً من تثبيته للاستخدام الواسع للنظام. ومع ذلك ، يمكن أيضًا استخدام البرنامج النصي لـ Enkits 'Cmake لتثبيت المكتبة إذا تم تعيين متغير ENKITS_INSTALL Cmake 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 هو مجردة 6 درجات من لعبة فوكسل الحرية. تم تطوير Enkits للاستخدام في Avoyd في محركنا في المنزل.

GPU/وحدة المعالجة المركزية مولد نسيج
رمز Aras Pranckeviusius لسلسلته على تجارب تتبع المسار اليومية مع لغات مختلفة.
.
كتاب ماركو كاستورينا وجابرييل ساسون حول تطوير محرك عرض حديث من المبادئ الأولى باستخدام Vulkan API. يتم استخدام Enkits كمكتبة المهام لتوزيع العمل عبر النوى.
حقوق الطبع والنشر (C) 2013-2020 Doug Binks
يتم توفير هذا البرنامج "AS-IS" ، دون أي ضمان صريح أو ضمني. لن يتحمل المؤلفون بأي حال من الأحوال مسؤولية أي أضرار تنشأ عن استخدام هذا البرنامج.
يتم منح الإذن لأي شخص لاستخدام هذا البرنامج لأي غرض ، بما في ذلك التطبيقات التجارية ، وتغييره وإعادة توزيعه بحرية ، مع مراعاة القيود التالية: