ডাইরেক্টএক্স 10 শেডারে বিবৃতিগুলি এড়িয়ে চলুন?


14

আমি শুনেছি যদি ছায়াময়গুলিতে বিবৃতিগুলি এড়ানো উচিত, কারণ বিবৃতিগুলির উভয় অংশই কার্যকর করা হবে এবং ভুলের চেয়ে বাদ দেওয়া হবে (যা কার্য সম্পাদনকে ক্ষতিগ্রস্থ করে)।

ডাইরেক্টএক্স 10 এ এখনও সমস্যা? কেউ আমাকে বলেছিলেন, এতে কেবলমাত্র ডান শাখা চালানো হবে।

দৃষ্টান্তের জন্য আমার কাছে কোডটি রয়েছে:

float y1 = 5; float y2 = 6; float b1 = 2; float b2 = 3;

if(x>0.5){
    x = 10 * y1 + b1;
}else{
    x = 10 * y2 + b2;
}

এটি দ্রুত করার কোনও অন্য উপায় আছে?

যদি তাই হয়, কিভাবে এটি?

উভয় শাখা একই রকম দেখায়, কেবলমাত্র পার্থক্যটি "ধ্রুবক" এর মান ( y1, y2, b1, b2পিক্সেল শ্যাডারে সমস্ত পিক্সেলের জন্য একই) are


1
সত্যিই, এটি খুব অকালীন অপটিমাইজেশন, আপনি নিজের কোডটি বেঞ্চমার্ক না করে এবং 100% শেডার বাধা না হওয়া পর্যন্ত কেবল তাদের পরিবর্তন করবেন না।
pwny

উত্তর:


17

মাইক্রো-অপ্টিমাইজিং শেডারগুলির জন্য অনেকগুলি নিয়ম ভেক্টর এক্সটেনশানগুলির সাথে traditionalতিহ্যবাহী সিপিইউগুলির মতো। এখানে কয়েকটি ইঙ্গিত দেওয়া হল:

  • বিল্ট-ইন টেস্ট ফাংশন রয়েছে ( test, lerp/ mix)
  • দুটি ভেক্টর যুক্ত করার জন্য দুটি ফ্লোট যুক্ত করার মতো খরচ হয়
  • সুইজলিং বিনামূল্যে

এটি সত্য যে শাখাগুলি আধুনিক হার্ডওয়্যারগুলিতে আগের তুলনায় সস্তা, তবে সম্ভব হলে এগুলি এড়ানো আরও ভাল। সুইজলিং এবং টেস্ট ফাংশনগুলি ব্যবহার করে আপনি পরীক্ষা ছাড়াই আপনার শেডারটি আবার লিখতে পারেন:

/* y1, y2, b1, b2 */
float4 constants = float4(5, 6, 2, 3);

float2 tmp = 10 * constants.xy + constants.zw;
x = lerp(tmp[1], tmp[0], step(x, 0.5));

দুটি মানের মধ্যে বাছাই করার জন্য ব্যবহার করা stepএবং lerpএটি একটি প্রচলিত প্রজ্ঞা।


6

সাধারণত এটি ঠিক আছে। শেডারগুলি উল্লম্ব বা পিক্সেলের গ্রুপগুলিতে চালিত করবে (বিভিন্ন বিক্রেতাদের এগুলির জন্য আলাদা পরিভাষা রয়েছে তাই আমি এ থেকে দূরে রাখছি) এবং যদি কোনও গোষ্ঠীর সমস্ত উল্লম্ব বা পিক্সেল একই পথ অবলম্বন করে তবে শাখাগুলি ব্যয় নগদ নয়।

শেডার সংকলকটিতে আপনার বিশ্বাস করা দরকার। আপনি যে এইচএলএসএল কোডটি লিখেছেন তা বাইটকোড বা এমনকি সমাবেশের সরাসরি উপস্থাপনা হিসাবে দেখা উচিত নয় যা এটি সংকলিত হবে এবং সংকলকটি একে সমতুল্য কিছুতে রূপান্তর করতে পুরোপুরি মুক্ত তবে শাখাটি এড়িয়ে চলে (উদাঃ কখনও কখনও লিটারপ হতে পারে) একটি পছন্দসই রূপান্তর)। অন্যদিকে, যদি সংকলকটি নির্ধারণ করে যে কোনও শাখা সম্পাদন করা আসলেই দ্রুত গতিপথ, এটি এটি একটি শাখায় সংকলন করবে। পিক্স বা অনুরূপ সরঞ্জামে উত্পন্ন সমাবেশটি এখানে খুব সহায়ক হতে পারে।

অবশেষে, পুরানো জ্ঞানটি এখনও এখানে ধরে রেখেছে - এটির প্রোফাইল দিন, এটি আসলে আপনার জন্য কোনও পারফরম্যান্সের সমস্যা কিনা তা নির্ধারণ করুন এবং এরপরে নয়, এরপরে মোকাবেলা করুন। ধরে নেওয়া যে কোনও কিছু পারফরম্যান্সের সমস্যা হতে পারে এবং সেই অনুমান অনুযায়ী কাজ করা কেবল পরে বড় সমস্যাগুলির এক বিশাল ঝুঁকির কারণ হতে পারে।


4

রবার্ট রুহানি পোস্ট করা লিঙ্ক / নিবন্ধ থেকে উদ্ধৃতি:

"কন্ডিশন কোড (পূর্বাভাস) পুরানো আর্কিটেকচারগুলিতে সত্য ব্রাঞ্চিং অনুকরণ করার জন্য ব্যবহৃত হয়। তবে যদি এই স্থাপত্যগুলিতে সংকলিত বিবৃতিগুলি অবশ্যই সমস্ত টুকরাগুলিতে নেওয়া এবং না নেওয়া উভয় শাখার নির্দেশনার মূল্যায়ন করতে হয়। শাখার শর্তটি মূল্যায়ন করা হয় এবং একটি শর্ত কোড সেট করা হয়।" শাখার প্রতিটি অংশের নির্দেশাবলী অবশ্যই রেজিস্টারগুলিতে ফলাফল লেখার আগে শর্ত কোডের মানটি পরীক্ষা করতে হবে ফলস্বরূপ, নেওয়া শাখাগুলিতে কেবল নির্দেশাবলী তাদের আউটপুট লিখবে এইভাবে, এই স্থাপত্যগুলিতে সমস্ত শাখার উভয় অংশেরই দাম পড়বে শাখা, এবং শাখার শর্ত মূল্যায়নের জন্য ব্যয় such এই জাতীয় আর্কিটেকচারে খুব কম শাখাগুলি ব্যবহার করা উচিত N এনভিআইডিএ জিফোর্স এফএক্স সিরিজ জিপিইউগুলি তাদের টুকরা প্রসেসরে শর্ত-কোড শাখা অনুকরণ ব্যবহার করে ""

এমএইচ 01 তে যেমন পরামর্শ দিয়েছে ("পিআইএক্সে উত্পন্ন অ্যাসেমব্লি দেখতে দেখতে বা একই জাতীয় সরঞ্জামটি এখানে খুব সহায়ক হতে পারে" "), আপনার আউটপুট পরীক্ষা করতে একটি সংকলক সরঞ্জাম ব্যবহার করা উচিত। আমার অভিজ্ঞতায় এনভিডিয়া'র সিজি টুল (সিজি এখনও ক্রস প্ল্যাটফর্ম সক্ষমতার কারণে বিস্তৃতভাবে ব্যবহৃত হয়) জিপিইউ রত্ন শর্তের কোডগুলি (পূর্বাভাস) অনুচ্ছেদে উল্লিখিত আচরণের একটি নিখুঁত চিত্রণ দিয়েছে । সুতরাং, ট্রিগার মান নির্বিশেষে, উভয় শাখা প্রতিটি খণ্ড ভিত্তিতে মূল্যায়ন করা হয়েছিল এবং কেবল শেষে ডানটি আউটপুট রেজিস্ট্রিতে রাখা হয়েছিল। তবুও, গণনার সময় নষ্ট হয়েছিল। সেই সময়ে, আমি ভেবেছিলাম যে শাখাবিন্যাস ইচ্ছা সাহায্যের কর্মক্ষমতা, বিশেষ করে, কারণ সবসেই শাডারে থাকা টুকরোগুলি ডান শাখায় সিদ্ধান্ত নেওয়ার জন্য অভিন্ন মানের উপর নির্ভর করেছিল - যা উদ্দেশ্য হিসাবে ঘটেনি। সুতরাং, এখানে একটি বড় সাবধানবাণী (যেমন - উবারশাদেরকে এড়িয়ে চলুন - সম্ভবত জাহান্নামের শাখা প্রশাখার বৃহত্তম উত্স)।


2

আপনার যদি ইতিমধ্যে পারফরম্যান্স সমস্যা না থাকে তবে এটি ঠিক আছে। ধ্রুবকের সাথে তুলনা করার জন্য ব্যয়টি এখনও খুব সস্তা। এখানে জিপিইউ শাখা প্রশস্তকরণ সম্পর্কে একটি ভাল পঠন এখানে রয়েছে: http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter34.html

নির্বিশেষে, এখানে কোডের একটি স্নিপেট রয়েছে যা যদি বিবৃতিটির তুলনায় আরও খারাপ হতে পারে (এবং এটি খুব কম পঠনযোগ্য / রক্ষণাবেক্ষণযোগ্য) তবে তবুও এটি থেকে মুক্তি পেয়ে যায়:

int fx = floor(x);
int y = (fx * y2) + ((1- fx) * y1);
int b = (fx * b2) + ((1 -fx) * b1);

x = 10 * y + b;

নোট করুন যে আমি অনুমানটি করছি যে এক্স সীমার মধ্যে সীমাবদ্ধ [0, 1]। X> = 2 বা x <0 হলে এটি কাজ করবে না।

কি যে স্নিপেড করে হয় ধর্মান্তরিত হল x 0অথবা 1এবং সংখ্যাবৃদ্ধি 0 দ্বারা ভুল এক এবং 1 দ্বারা অন্যান্য করুন।


যেহেতু মূল পরীক্ষা if(x<0.5)মান fxহওয়া উচিত round(x)বা floor(x + 0.5)
সাম হোচেভার

1

শাখা ছাড়াই শর্ত করতে সক্ষম একাধিক নির্দেশ রয়েছে;

vec4 when_eq(vec4 x, vec4 y) {
  return 1.0 - abs(sign(x - y));
}

vec4 when_neq(vec4 x, vec4 y) {
  return abs(sign(x - y));
}

vec4 when_gt(vec4 x, vec4 y) {
  return max(sign(x - y), 0.0);
}

vec4 when_lt(vec4 x, vec4 y) {
  return max(sign(y - x), 0.0);
}

vec4 when_ge(vec4 x, vec4 y) {
  return 1.0 - when_lt(x, y);
}

vec4 when_le(vec4 x, vec4 y) {
  return 1.0 - when_gt(x, y);
}

প্লাস কিছু লজিকাল অপারেটর;

vec4 and(vec4 a, vec4 b) {
  return a * b;
}

vec4 or(vec4 a, vec4 b) {
  return min(a + b, 1.0);
}

vec4 xor(vec4 a, vec4 b) {
  return (a + b) % 2.0;
}

vec4 not(vec4 a) {
  return 1.0 - a;
}

উত্স: http://theorangeduck.com/page/avoider-shader-conditions

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.