Komputeإطار حساب حساب GPU للأغراض العامة لبطاقات رسومات البائع المتقاطعة (AMD ، Qualcomm ، Nvidia & Friends) |
انضم إلى مكالمات Discord & Community؟ منشور مدونة الوثائق ⌨ أمثلة؟
أدناه يمكنك العثور على مثال لضرب GPU باستخدام واجهات C ++ و Python Kompute.
يمكنك الانضمام إلى Discord للأسئلة / المناقشة ، أو فتح مشكلة github ، أو قراءة الوثائق.
توفر واجهة C ++ الوصول إلى مستوى منخفض إلى المكونات الأصلية لـ Kompute ، مما يتيح للتحسينات المتقدمة وكذلك تمديد المكونات.
void kompute ( const std::string& shader) {
// 1. Create Kompute Manager with default settings (device 0, first queue and no extensions)
kp::Manager mgr;
// 2. Create and initialise Kompute Tensors through manager
// Default tensor constructor simplifies creation of float values
auto tensorInA = mgr. tensor ({ 2 ., 2 ., 2 . });
auto tensorInB = mgr. tensor ({ 1 ., 2 ., 3 . });
// Explicit type constructor supports uint32, int32, double, float and bool
auto tensorOutA = mgr. tensorT < uint32_t >({ 0 , 0 , 0 });
auto tensorOutB = mgr. tensorT < uint32_t >({ 0 , 0 , 0 });
std::vector<std::shared_ptr<kp::Memory>> params = {tensorInA, tensorInB, tensorOutA, tensorOutB};
// 3. Create algorithm based on shader (supports buffers & push/spec constants)
kp::Workgroup workgroup ({ 3 , 1 , 1 });
std::vector< float > specConsts ({ 2 });
std::vector< float > pushConstsA ({ 2.0 });
std::vector< float > pushConstsB ({ 3.0 });
auto algorithm = mgr. algorithm (params,
// See documentation shader section for compileSource
compileSource (shader),
workgroup,
specConsts,
pushConstsA);
// 4. Run operation synchronously using sequence
mgr. sequence ()
-> record <kp::OpSyncDevice>(params)
-> record <kp::OpAlgoDispatch>(algorithm) // Binds default push consts
-> eval () // Evaluates the two recorded operations
-> record <kp::OpAlgoDispatch>(algorithm, pushConstsB) // Overrides push consts
-> eval (); // Evaluates only last recorded operation
// 5. Sync results from the GPU asynchronously
auto sq = mgr. sequence ();
sq-> evalAsync <kp::OpSyncLocal>(params);
// ... Do other work asynchronously whilst GPU finishes
sq-> evalAwait ();
// Prints the first output which is: { 4, 8, 12 }
for ( const float & elem : tensorOutA-> vector ()) std::cout << elem << " " ;
// Prints the second output which is: { 10, 10, 10 }
for ( const float & elem : tensorOutB-> vector ()) std::cout << elem << " " ;
} // Manages / releases all CPU and GPU memory resources
int main () {
// Define a raw string shader (or use the Kompute tools to compile to SPIRV / C++ header
// files). This shader shows some of the main components including constants, buffers, etc
std::string shader = ( R"(
#version 450
layout (local_size_x = 1) in;
// The input tensors bind index is relative to index in parameter passed
layout(set = 0, binding = 0) buffer buf_in_a { float in_a[]; };
layout(set = 0, binding = 1) buffer buf_in_b { float in_b[]; };
layout(set = 0, binding = 2) buffer buf_out_a { uint out_a[]; };
layout(set = 0, binding = 3) buffer buf_out_b { uint out_b[]; };
// Kompute supports push constants updated on dispatch
layout(push_constant) uniform PushConstants {
float val;
} push_const;
// Kompute also supports spec constants on initalization
layout(constant_id = 0) const float const_one = 0;
void main() {
uint index = gl_GlobalInvocationID.x;
out_a[index] += uint( in_a[index] * in_b[index] );
out_b[index] += uint( const_one * push_const.val );
}
)" );
// Run the function declared above with our raw string shader
kompute (shader);
}
توفر حزمة Python واجهة تفاعلية عالية المستوى تتيح التجريب مع ضمان أداء عمل عالي الأداء وتطوير سريع.
from . utils import compile_source # using util function from python/test/utils
def kompute ( shader ):
# 1. Create Kompute Manager with default settings (device 0, first queue and no extensions)
mgr = kp . Manager ()
# 2. Create and initialise Kompute Tensors through manager
# Default tensor constructor simplifies creation of float values
tensor_in_a = mgr . tensor ([ 2 , 2 , 2 ])
tensor_in_b = mgr . tensor ([ 1 , 2 , 3 ])
# Explicit type constructor supports uint32, int32, double, float and bool
tensor_out_a = mgr . tensor_t ( np . array ([ 0 , 0 , 0 ], dtype = np . uint32 ))
tensor_out_b = mgr . tensor_t ( np . array ([ 0 , 0 , 0 ], dtype = np . uint32 ))
assert ( t_data . data_type () == kp . DataTypes . uint )
params = [ tensor_in_a , tensor_in_b , tensor_out_a , tensor_out_b ]
# 3. Create algorithm based on shader (supports buffers & push/spec constants)
workgroup = ( 3 , 1 , 1 )
spec_consts = [ 2 ]
push_consts_a = [ 2 ]
push_consts_b = [ 3 ]
# See documentation shader section for compile_source
spirv = compile_source ( shader )
algo = mgr . algorithm ( params , spirv , workgroup , spec_consts , push_consts_a )
# 4. Run operation synchronously using sequence
( mgr . sequence ()
. record ( kp . OpTensorSyncDevice ( params ))
. record ( kp . OpAlgoDispatch ( algo )) # Binds default push consts provided
. eval () # evaluates the two recorded ops
. record ( kp . OpAlgoDispatch ( algo , push_consts_b )) # Overrides push consts
. eval ()) # evaluates only the last recorded op
# 5. Sync results from the GPU asynchronously
sq = mgr . sequence ()
sq . eval_async ( kp . OpTensorSyncLocal ( params ))
# ... Do other work asynchronously whilst GPU finishes
sq . eval_await ()
# Prints the first output which is: { 4, 8, 12 }
print ( tensor_out_a )
# Prints the first output which is: { 10, 10, 10 }
print ( tensor_out_b )
if __name__ == "__main__" :
# Define a raw string shader (or use the Kompute tools to compile to SPIRV / C++ header
# files). This shader shows some of the main components including constants, buffers, etc
shader = """
#version 450
layout (local_size_x = 1) in;
// The input tensors bind index is relative to index in parameter passed
layout(set = 0, binding = 0) buffer buf_in_a { float in_a[]; };
layout(set = 0, binding = 1) buffer buf_in_b { float in_b[]; };
layout(set = 0, binding = 2) buffer buf_out_a { uint out_a[]; };
layout(set = 0, binding = 3) buffer buf_out_b { uint out_b[]; };
// Kompute supports push constants updated on dispatch
layout(push_constant) uniform PushConstants {
float val;
} push_const;
// Kompute also supports spec constants on initalization
layout(constant_id = 0) const float const_one = 0;
void main() {
uint index = gl_GlobalInvocationID.x;
out_a[index] += uint( in_a[index] * in_b[index] );
out_b[index] += uint( const_one * push_const.val );
}
"""
kompute ( shader )يمكنك تجربة دفاتر Noteboys التفاعلية Colab التي تسمح لك باستخدام وحدة معالجة الرسومات المجانية. الأمثلة المتاحة هي أمثلة Python و C ++ أدناه:
جرب C ++ Colab التفاعلي من منشور المدونة | جرب Python Colab التفاعلي من منشور المدونة |
يمكنك أيضًا الاطلاع على المحادثتين التاليتين المقدمتين في مؤتمر FOSDEM 2021.
يحتوي كلا الفيديوهات على الطوابع الزمنية التي تتيح لك تخطي القسم الأكثر صلة لك - المقدمة والدوافع لكليهما هي نفسها تقريبًا حتى تتمكن من تخفيف المحتوى الأكثر تحديدًا.
شاهد الفيديو لعشاق C ++ | شاهد مقطع الفيديو لعشاق التعلم الآلي والآلي |
تتضمن الهندسة المعمارية الأساسية لـ Kompute ما يلي:
لرؤية انهيار كامل يمكنك القراءة أكثر في مرجع فئة C ++.
| الهندسة المعمارية الكاملة | مكونات kompute مبسطة |
|---|---|
(صغير جدًا ، تحقق من الرسم البياني المرجعي الكامل في مستندات للحصول على التفاصيل) |
يوفر Kompute المرونة لتشغيل العمليات بطريقة غير متزامنة من خلال VK :: Bences. علاوة على ذلك ، يمكّن Kompute لتخصيص قوائم الانتظار الصريحة ، والتي تسمح بالتنفيذ الموازي للعمليات عبر عائلات قائمة الانتظار.
توفر الصورة أدناه الحدس حول كيفية تخصيص تسلسل Kompute لقوائم مختلفة لتمكين التنفيذ المتوازي بناءً على الأجهزة. يمكنك رؤية الأيدي على سبيل المثال ، بالإضافة إلى صفحة الوثائق التفصيلية التي تصف كيف ستعمل باستخدام NVIDIA 1650 كمثال.
تم تحسين Kompute للعمل في بيئات الهاتف المحمول. يمكّن نظام الإنشاء للتحميل الديناميكي لمكتبة Vulkan المشتركة لبيئات Android ، إلى جانب غلاف Android NDK يعمل لروايات CPP.
من أجل الغوص العميق الكامل ، يمكنك قراءة منشور المدونة "Supercrading تطبيقات الهاتف المحمول الخاصة بك مع GPU على مستوى الجهاز المعجل الآلي". يمكنك أيضًا الوصول إلى رمز المثال الشامل في المستودع ، والذي يمكن تشغيله باستخدام Android Studio. |
إلى جانب C ++ Core SDK ، يمكنك أيضًا استخدام حزمة Python من Kompute ، والتي تكشف نفس الوظيفة الأساسية ، ويدعم قابلية التشغيل البيني مع كائنات Python مثل القوائم ، صفائف numpy ، إلخ.
التبعيات الوحيدة هي Python 3.5+ و Cmake 3.4.1+. يمكنك تثبيت Kompute من حزمة Python Pypi باستخدام الأمر التالي.
pip install kp
يمكنك أيضًا التثبيت من Master Branch باستخدام:
pip install git+git://github.com/KomputeProject/kompute.git@master
لمزيد من التفاصيل ، يمكنك قراءة وثائق Python Package أو وثائق مرجع فئة Python.
يستخدم نظام البناء المقدم cmake ، والذي يسمح ببناء منصة متقاطعة.
يوفر Makefile الأعلى مستوى مجموعة من التكوينات المحسنة للتطوير وكذلك بناء صورة Docker ، ولكن يمكنك بدء بناء مع الأمر التالي:
cmake -Bbuild
يمكنك أيضًا إضافة kompute في repo الخاص بك باستخدام add_subdirectory - يوضح ملف Android مثال Cmakelists.txt كيف سيتم ذلك.
للحصول على نظرة عامة أكثر تقدماً على تكوين الإنشاء ، تحقق من وثائق البناء Deep Dive.
نحن نقدر PRS والقضايا. إذا كنت ترغب في المساهمة ، فحاول التحقق من علامة "الإصدار الأول الجيد" ، ولكن حتى استخدام مشكلات Kompute والإبلاغ هو مساهمة كبيرة!
إذا كنت ترغب في التشغيل باستخدام طبقات التصحيح ، فيمكنك إضافتها باستخدام معلمة KOMPUTE_ENV_DEBUG_LAYERS على النحو التالي:
export KOMPUTE_ENV_DEBUG_LAYERS="VK_LAYER_LUNARG_api_dump"
لتحديث الوثائق التي ستحتاج إليها:
make push_docs_to_ghpages تم تبسيط اختبارات الوحدة بشكل كبير للمساهمين.
يتم إجراء الاختبارات على وحدة المعالجة المركزية ، ويمكن تشغيلها باستخدام واجهة سطر الأوامر ACT (https://github.com/nektos/act) - بمجرد تثبيت سطر الأوامر (وابدأ Docker Daemon) عليك فقط كتابة:
$ act
[Python Tests/python-tests] Start image=axsauze/kompute-builder:0.2
[C++ Tests/cpp-tests ] Start image=axsauze/kompute-builder:0.2
[C++ Tests/cpp-tests ] ? docker run image=axsauze/kompute-builder:0.2 entrypoint=["/usr/bin/tail" "-f" "/dev/null"] cmd=[]
[Python Tests/python-tests] ? docker run image=axsauze/kompute-builder:0.2 entrypoint=["/usr/bin/tail" "-f" "/dev/null"] cmd=[]
...
يحتوي المستودع على اختبارات الوحدة لرمز C ++ ورمز Python ، ويمكن العثور عليه ضمن مجلد test/ python/test .
يتم تشغيل الاختبارات حاليًا من خلال CI باستخدام إجراءات GitHub. ويستخدم الصور الموجودة في docker-builders/ .
من أجل تقليل متطلبات الأجهزة ، يمكن إجراء الاختبارات بدون وحدة معالجة الرسومات ، مباشرة في وحدة المعالجة المركزية باستخدام SwiftShader.
لمزيد من المعلومات حول كيفية إعداد CI والاختبارات ، يمكنك الانتقال إلى قسم CI و Docker واختبارات في الوثائق.
بدأ هذا المشروع بعد أن رأى أن الكثير من مشاريع ML & DL الجديدة والمشهورة مثل Pytorch و TensorFlow و Alibaba DNN و Tencent NCNN - من بين أمور أخرى - إما متكاملة أو تتطلع إلى دمج دعم Vulkan SDK لإضافة GPU المتنقلة (والبائع المتقاطع).
يوفر Vulkan SDK واجهة منخفضة المستوى منخفضة تتيح التحسينات المتخصصة للغاية - ومع ذلك فإنها تأتي بتكلفة رمز مطوّل للغاية يتطلب 500-2000 سطر من التعليمات البرمجية لبدء كتابة رمز التطبيق. وقد نتج عن ذلك كل من هذه المشاريع التي يتعين عليها تنفيذ نفس خط الأساس لتجريد الميزات غير المرتبطة بالوكالة من فولكان SDK. يمكن أن تؤدي هذه الكمية الكبيرة من لوحة المرجل غير المعيارية إلى نقل محدودة للمعرفة ، وفرصة أعلى لخلل تنفيذ إطار فريد من نوعها ، وما إلى ذلك.
نقوم حاليًا بتطوير Kompute بعدم إخفاء واجهة Vulkan SDK (كما هو مصمم بشكل جيد بشكل لا يصدق) ولكن لزيادة التركيز المباشر على إمكانيات الحوسبة في GPU من Vulkan SDK. توفر هذه المقالة نظرة عامة على مستوى عالٍ على دوافع Kompute ، إلى جانب مجموعة من الأمثلة على الأمثلة التي تقدم كل من حوسبة GPU وكذلك بنية Kompute الأساسية.