ক্লাসের সীমাবদ্ধতার সাথে একটি ফাংশন বিশেষজ্ঞ করার জন্য আমার 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
যতটা দ্রুত করা । আমি এটি করার দুটি উপায় খুঁজে পেয়েছি:vtTest
plusFastCyc
- স্পষ্টতা কল
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
। এটি কাজটি সেরে ফেলেছে তবে আসল প্রোগ্রামে নির্দিষ্ট ফ্যান্টম ধরণের জন্য তাদের বিশেষায়িত করা যায় না কারণ এগুলি পুনরায় সংশোধিত হয়েছে।