ক্লাসের সীমাবদ্ধতার সাথে একটি ফাংশন বিশেষজ্ঞ করার জন্য আমার GHC পেতে সমস্যা হচ্ছে। আমি এখানে নিলাম আমার সমস্যার একটি সংক্ষিপ্ত উদাহরণ আছে: Foo.hs এবং Main.hs । দুটি ফাইল সংকলন করে (জিএইচসি 7.6.2, ghc -O3 Main) এবং রান করে।
দ্রষ্টব্য:
Foo.hs সত্যই নিচে নামানো হয়। সীমাবদ্ধতার প্রয়োজন কেন আপনি যদি দেখতে চান তবে আপনি এখানে আরও কিছু কোড দেখতে পারেন । যদি আমি কোডটি একটি ফাইলে রাখি বা অন্য অনেকগুলি ছোটখাটো পরিবর্তন করি তবে জিএইচসি কেবলমাত্র কলটিতে ইনলাইন করে plusFastCyc। এটি বাস্তব কোডে ঘটবে না কারণ plusFastCycজিএইচসির পক্ষে ইনলাইন করা খুব বড়, এমনকি চিহ্নিত থাকলেও INLINE। বিষয়টি হ'ল কলটি বিশেষায়িত করা plusFastCyc, এটি ইনलाइन নয়। plusFastCycরিয়েল কোডে অনেক জায়গায় ডাকা হয়, সুতরাং আমি যদি জিএইচসি এটি করতে বাধ্য করতে পারি তবে এত বড় ফাংশনটির নকল করা বাঞ্ছনীয় নয়।
সুদের কোড plusFastCycমধ্যে Foo.hs, এখানে পুনরুত্পাদন:
{-# INLINEABLE plusFastCyc #-}
{-# SPECIALIZE plusFastCyc ::
forall m . (Factored m Int) =>
(FastCyc (VT U.Vector m) Int) ->
(FastCyc (VT U.Vector m) Int) ->
(FastCyc (VT U.Vector m) Int) #-}
-- Although the next specialization makes `fcTest` fast,
-- it isn't useful to me in my real program because the phantom type M is reified
-- {-# SPECIALIZE plusFastCyc ::
-- FastCyc (VT U.Vector M) Int ->
-- FastCyc (VT U.Vector M) Int ->
-- FastCyc (VT U.Vector M) Int #-}
plusFastCyc :: (Num (t r)) => (FastCyc t r) -> (FastCyc t r) -> (FastCyc t r)
plusFastCyc (PowBasis v1) (PowBasis v2) = PowBasis $ v1 + v2
Main.hs: ফাইল দুটি ড্রাইভার হয়েছে vtTest, যা ~ 3 সেকেন্ডের মধ্যে সঞ্চালিত হয়, এবং fcTestযখন ব্যবহার -O3 সঙ্গে কম্পাইল যা ~ 83 সেকেন্ডের মধ্যে চালায়, forall'ঘ বিশেষজ্ঞতা।
কোর শো যে জন্য vtTestপরীক্ষা, উপরন্তু কোডে বিশেষ হচ্ছে Unboxedওভার ভেক্টর Int, এস, ইত্যাদি যখন জেনেরিক ভেক্টর কোড জন্য ব্যবহার করা হয় fcTest। লাইন 10, আপনি দেখতে পারেন যে GHC একটি বিশেষ সংস্করণ লেখে কী করে plusFastCycআমি বিশ্বাস করি এই নিয়ম লাইন 270. (চালু ফায়ার উচিত লাইন 167 বিশেষজ্ঞতা জন্য নিয়ম লাইন 225. হয় জেনেরিক সংস্করণ তুলনায় main6কল iterate main8 y, তাই main8হয় যেখানে plusFastCycবিশেষজ্ঞ করা উচিত।)
আমার লক্ষ্যটি বিশেষজ্ঞের দ্বারা fcTestযতটা দ্রুত করা । আমি এটি করার দুটি উপায় খুঁজে পেয়েছি:vtTestplusFastCyc
- স্পষ্টতা কল
inlineথেকেGHC.ExtsএfcTest। - অপসারণ
Factored m Intসীমাবদ্ধতা করুনplusFastCyc।
বিকল্প 1টি অসন্তুষ্টিজনক কারণ আসল কোড বেসে plusFastCycপ্রায়শই ব্যবহৃত ক্রিয়াকলাপ এবং খুব বড় ফাংশন, তাই এটি প্রতিটি ব্যবহারের সাথে linedোকানো উচিত নয়। বরং, জিএইচসি এর একটি বিশেষ সংস্করণ কল করা উচিত plusFastCyc। বিকল্প 2 আসলে কোনও বিকল্প নয় কারণ আমার আসল কোডে প্রতিবন্ধকতা প্রয়োজন।
আমি ব্যবহার (এবং ব্যবহার করছেন না) অপশন বিভিন্ন চেষ্টা করেছি INLINE, INLINABLEএবং SPECIALIZE, কিন্তু কিছুই কাজ মনে হয়। ( সম্পাদনা : আমি plusFastCycআমার উদাহরণটি ছোট করে তুলতে খুব বেশি চেষ্টা করতে পেরেছি, সুতরাং INLINEফাংশনটি অন্তর্ভুক্ত হতে পারে This এটি আমার প্রকৃত কোডে ঘটে না কারণ plusFastCycএত বড়)) এই বিশেষ উদাহরণে, আমি না যে কোনও match_co: needs more casesবা RULE: LHS too complicated to desugar(এবং এখানে ) সতর্কতা পাওয়া, যদিও আমি অনেক পেয়েছিলামmatch_co উদাহরণটি হ্রাস করার আগে সতর্কতা । সম্ভবত, "সমস্যা" হ'ল Factored m Intনিয়মের প্রতিবন্ধকতা; আমি যদি এই সীমাবদ্ধতায় পরিবর্তন করি, fcTestতত দ্রুত চলে vtTest।
আমি কি এমন কিছু করছি যা ঠিক পছন্দ করে না? জিএইচসি কেন বিশেষজ্ঞ হবে না plusFastCycএবং আমি কীভাবে এটি তৈরি করতে পারি?
হালনাগাদ
জিএইচসি 7.8.2 এ সমস্যাটি থেকেই যায়, তাই এই প্রশ্নটি এখনও প্রাসঙ্গিক।
m, যথাM। এটি কাজটি সেরে ফেলেছে তবে আসল প্রোগ্রামে নির্দিষ্ট ফ্যান্টম ধরণের জন্য তাদের বিশেষায়িত করা যায় না কারণ এগুলি পুনরায় সংশোধিত হয়েছে।