ما هو الفرق بين إنشاء كائن عازلة مع clCreateBuffer + CL_MEM_COPY_HOST_PTR مقابل clcreatebuffer + clenqueuewriteBuffer؟

StackOverflow https://stackoverflow.com/questions/3832963

  •  26-09-2019
  •  | 
  •  

سؤال

لقد رأيت كلا الإصدارين في البرامج التعليمية ، لكنني لم أتمكن من معرفة ما هي مزاياها وعيوبها. أي واحد هو الصحيح؟

cl_mem input = clCreateBuffer(context,CL_MEM_READ_ONLY,sizeof(float) * DATA_SIZE, NULL, NULL);
clEnqueueWriteBuffer(command_queue, input, CL_TRUE, 0, sizeof(float) * DATA_SIZE, inputdata, 0, NULL, NULL);

ضد.

cl_mem input = clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, ,sizeof(float) * DATA_SIZE, inputdata, NULL);

شكرًا.

تحديث

أضفت CL_MEM_COPY_HOST_PTR, إلى المثال الثاني لجعله صحيحًا.

هل كانت مفيدة؟

المحلول

أفترض أن InputData ليس فارغًا.

في هذه الحالة ، لا ينبغي أن يعمل النهج الثاني على الإطلاق ، لأن المواصفات تقول ، أن clcreatebuffer يعيد فارغًا وخطأ ، إذا:

CL_INVALID_HOST_PTR إذا كان HOST_PTR فارغًا و CL_MEM_USE_HOST_PTR أو CL_MEM_COPY_HOST_PTR يتم تعيينه في الأعلام أو إذا لم يتم تعيين ass_ptr في الأعلام ولكن cl_mem_copy_host_ptr أو cl_mem_use_host_ptr غير محددة في الأعلام.

لذلك تقصد أيضا

clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,sizeof(float) * DATA_SIZE, inputdata, NULL);

أو

clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR,sizeof(float) * DATA_SIZE, inputdata, NULL);

يجب أن يكون الأول أولًا أو أقل مثل النهج الأول الذي أظهرته ، في حين أن الثانية لن تنسخ البيانات بالفعل ، ولكن بدلاً من ذلك استخدم موقع الذاكرة المرفق لتخزين المخزن المؤقت (أجزاء التخزين المؤقت أو كلها في ذاكرة الجهاز) . أي من هذين الشخصين يعتمد بشكل أفضل على سيناريو الاستخدام بشكل واضح.

Personaly أفضل استخدام نهج خطوتين في تخصيص المخزن المؤقت أولاً ، وبعد ذلك ملءه مع WriteTobuffer ، لأنني أجد أنه من الأسهل رؤية ما يحدث (بالطبع قد تكون خطوة واحدة أسرع (أو قد لا ، هذا مجرد تخمين)))

نصائح أخرى

خلال عملي مع OpenCl وجدت فرقًا مهمًا للغاية بين

cl_mem CT = clCreateImage3DContext, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR , Volume_format, X, Y, Z, rowPitch, slicePitch, sourceData, &error);

و

cl_mem CT = clCreateImage3D(Context, CL_MEM_READ_ONLY , Volume_format, X, Y, Z, 0, 0, 0, &error);
error = clEnqueueWriteImage(CommandQue, CT, CL_TRUE, origin, region, rowPitch, slicePitch, sourceData, 0, 0, 0);

للنهج الأول ، ستقوم OpenCl بنسخ مؤشر المضيف غير المباشر إلى وحدة معالجة الرسومات. أولاً ، سيتم تخصيص مخزن مؤقت مؤقت ثانٍ على المضيف والذي يمكن أن يسبب مشاكل إذا قمت بتحميل أشياء كبيرة مثل CT إلى وحدة معالجة الرسومات. لفترة قصيرة ، تكون الذاكرة المطلوبة ضعف حجم CT. أيضا لا يتم نسخ البيانات خلال هذه الوظيفة. يتم نسخه أثناء إعداد الوسيطة إلى وظيفة kernel التي تستخدم كائن الصورة ثلاثي الأبعاد.

النهج الثاني يوجه البيانات إلى وحدة معالجة الرسومات. لا توجد مخصصات إضافية قام بها OpenCl. أعتقد أن هذا ربما هو نفسه بالنسبة للكائنات العادية العادية.

الجانب الجميل من النهج الأول ، هو أن "clenqueuewriteBuffer" يسمح لك بتعيين حدث لنسخة المخزن المؤقت. لذلك ، دعنا نقول أنك تريد قياس الوقت الذي يستغرقه نسخ البيانات إلى وحدة معالجة الرسومات باستخدام خيارات GPU_Profiling ، ستتمكن من القيام بذلك مع النهج الأول ، ولكن ليس مع النظام الثاني.

النهج الثاني هو أكثر إحكاما ، وأسهل في القراءة ، ويتطلب خطوط أقل للرمز.

اختلاف رئيسي واحد واجهته في:

cl_mem input = clCreateBuffer(context,CL_MEM_READ_ONLY,sizeof(float) * DATA_SIZE, NULL, NULL); clEnqueueWriteBuffer(command_queue, input, CL_TRUE, 0, sizeof(float) * DATA_SIZE, inputdata, 0, NULL, NULL);

ستقوم هذه المجموعة الأولى من الأوامر بإنشاء مخزن مؤقت فارغ وأمر enqueue في قائمة انتظار أمرك لملء المخزن المؤقت.

cl_mem input = clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, ,sizeof(float) * DATA_SIZE, inputdata, NULL)

سيقوم هذا الأمر الثاني بإنشاء المخزن المؤقت وملءه على الفور. لاحظ أنه لا يوجد قائمة انتظار أمر في قائمة الوسيطة هذه ، لذلك يستخدم محتويات بيانات الإدخال كما هي الآن.

إذا كنت تقوم بالفعل بتشغيل رمز CL وكان مؤشر المصدر الخاص بك يعتمد على أمر سابق في قائمة انتظار الأوامر التي تكمل (على سبيل المثال قراءة enqueued لمخزن المؤقتة المسبقة السابقة) ، فأنت بالتأكيد تريد استخدام الطريقة الأولى. إذا حاولت إنشاء وملء المخزن المؤقت في أمر واحد ، فسوف ينتهي بهم المطاف بحالة سباق لن تنتظر فيها محتويات المخزن المؤقت بشكل صحيح على الانتهاء من قراءة المخزن المؤقت السابقة.

حسنًا ، الفرق الرئيسي بين هذين الاثنين هو أن أول واحد يخصص الذاكرة على الجهاز ثم يقوم بنسخ البيانات إلى تلك الذاكرة. الثاني يخصص فقط.

أم تقصد clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,sizeof(float) * DATA_SIZE, inputdata, NULL);?

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top