আমি একটি সাধারণ 2 ডি গেম ইঞ্জিন তৈরি করছি এবং আমি স্প্রেটগুলি বিভিন্ন থ্রেডে আপডেট এবং রেন্ডার করতে চাই, এটি কীভাবে করা হয় তা শিখতে।
আমার আপডেট থ্রেডটি সিঙ্ক্রোনাইজ করতে হবে এবং একটি রেন্ডার করতে হবে। বর্তমানে, আমি দুটি পারমাণবিক পতাকা ব্যবহার করি। কর্মপ্রবাহটি দেখতে এমন কিছু দেখাচ্ছে:
Thread 1 -------------------------- Thread 2
Update obj ------------------------ wait for swap
Create queue ---------------------- render the queue
Wait for render ------------------- notify render done
Swap render queues ---------------- notify swap done
এই সেটআপে আমি থ্রেডের এফপিএস আপডেট থ্রেডের এফপিএসের মধ্যে সীমাবদ্ধ করি। আমি sleep()
থ্রেডের এফপিএস রেন্ডার এবং আপডেট উভয়কেই সীমাবদ্ধ করতে ব্যবহার করি , সুতরাং দুটি অপেক্ষার ফাংশন বেশি সময় অপেক্ষা করবে না।
সমস্যা হল:
গড় সিপিইউ ব্যবহারের পরিমাণ প্রায় 0.1%। কখনও কখনও এটি 25% (কোয়াড কোর পিসিতে) পর্যন্ত যায়। এর অর্থ একটি থ্রেড অন্যটির জন্য অপেক্ষা করছে কারণ ওয়েট ফাংশনটি একটি পরীক্ষা এবং সেট ফাংশন সহ কিছুক্ষণ লুপ হয় এবং কিছুক্ষণ লুপ আপনার সমস্ত সিপিইউ সংস্থান ব্যবহার করবে।
আমার প্রথম প্রশ্নটি: দুটি থ্রেড সিঙ্ক্রোনাইজ করার অন্য কোনও উপায় আছে কি? আমি লক্ষ্য করেছি যে std::mutex::lock
কোনও সংস্থান লক করার অপেক্ষায় থাকাকালীন সিপিইউ ব্যবহার করবেন না যাতে এটি কিছুক্ষণ লুপ হয় না। এটা কিভাবে কাজ করে? আমি ব্যবহার করতে পারছি না std::mutex
কারণ আমার এগুলি একটি থ্রেডে লক করা এবং অন্য থ্রেডে আনলক করা দরকার।
অন্য প্রশ্নটি হ'ল; যেহেতু প্রোগ্রামটি সর্বদা 60 এফপিএসে চালিত হয় কেন কখনও কখনও তার সিপিইউ ব্যবহার 25% এ লাফিয়ে যায়, যার অর্থ এই যে দুটি অপেক্ষাগুলির মধ্যে একটির জন্য খুব বেশি অপেক্ষা করা হচ্ছে? (দুটি থ্রেড উভয়ই 60fps এর মধ্যেই সীমাবদ্ধ তাই আদর্শভাবে তাদের অনেকগুলি সংক্রামণের প্রয়োজন হবে না)।
সম্পাদনা: সমস্ত জবাবের জন্য ধন্যবাদ। প্রথমে আমি বলতে চাই যে আমি প্রতিটি ফ্রেম রেন্ডারের জন্য নতুন থ্রেড শুরু করি না। আমি উভয় আপডেট শুরু করি এবং শুরুতে লুপ রেন্ডার করি। আমি মনে করি মাল্টিথ্রেডিং কিছুটা সময় বাঁচাতে পারে: আমার নিম্নলিখিত ফাংশনগুলি রয়েছে: ফাস্টএলজি () এবং আলগ ()। আলগ () উভয়ই আমার আপডেট আপত্তি এবং রেন্ডার আপত্তি এবং ফাস্টালগ () হ'ল "রেন্ডারারে" রেন্ডার সারিটি is একক থ্রেডে:
Alg() //update
FastAgl()
Alg() //render
দুটি থ্রেডে:
Alg() //update while Alg() //render last frame
FastAlg()
সুতরাং সম্ভবত মাল্টিথ্রেডিং একই সময় সাশ্রয় করতে পারে। (প্রকৃতপক্ষে একটি সাধারণ গণিত অ্যাপ্লিকেশনটিতে এটি ব্যবহার করে, যেখানে আলাগুলি একটি দীর্ঘ অ্যালগরিদম amd ফাস্টালগ দ্রুততর হয়)
আমি জানি যে ঘুম কোনও ভাল ধারণা নয়, যদিও আমার কখনও সমস্যা হয় না। এই আরও ভাল হবে?
While(true)
{
If(timer.gettimefromlastcall() >= 1/fps)
Do_update()
}
তবে এটি এমন একটি অসীম হবে যখন লুপ সমস্ত সিপিইউ ব্যবহার করবে। আমি কি ব্যবহার সীমাবদ্ধ করতে ঘুম (একটি সংখ্যা <15) ব্যবহার করতে পারি? এইভাবে এটি চলবে, উদাহরণস্বরূপ, 100 fps, এবং আপডেট ফাংশনটি প্রতি সেকেন্ডে মাত্র 60 বার কল করা হবে।
দুটি থ্রেড সিঙ্ক্রোনাইজ করতে আমি ক্রিয়েটসিমফোরের সাথে ওয়েটারফোরসিংহলবজেক্টটি ব্যবহার করব যাতে আমি বিভিন্ন থ্রেডে লক এবং আনলক করতে সক্ষম হব (কিছুক্ষণ লুপ ব্যবহার করে হোয়াইটআউট), তাই না?