সীমাবদ্ধতাগুলির সাথে বিশেষীকরণ


156

ক্লাসের সীমাবদ্ধতার সাথে একটি ফাংশন বিশেষজ্ঞ করার জন্য আমার 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

  1. স্পষ্টতা কল inline থেকে GHC.ExtsfcTest
  2. অপসারণ 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 এ সমস্যাটি থেকেই যায়, তাই এই প্রশ্নটি এখনও প্রাসঙ্গিক।


3
আমি কেবল একটি নির্দিষ্ট জন্য বিশেষায়িত করার চেষ্টা করেছি m, যথা M। এটি কাজটি সেরে ফেলেছে তবে আসল প্রোগ্রামে নির্দিষ্ট ফ্যান্টম ধরণের জন্য তাদের বিশেষায়িত করা যায় না কারণ এগুলি পুনরায় সংশোধিত হয়েছে।
crockeea

আমি একটি জিএইচসি বাগ রিপোর্টটিও জমা দিয়েছি ghc.haskell.org/trac/ghc/ticket/8668 তবে সমস্যাটি এখনও খোলা আছে। বাগ রিপোর্ট প্রক্রিয়া আমাকে প্রশ্নটি কিছুটা পরিষ্কার করতে সহায়তা করেছে, তাই আশা করি কী হচ্ছে তা নির্ধারণ করা আরও সহজ হবে।
ক্রোকিয়া

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

1
আমি আমার মন্তব্যের সুরের জন্য ক্ষমাপ্রার্থী - এটি এই সাইটের পক্ষে আমার সেরা অবদান নয় - আপনার পোস্টে আসলেই কোনও ভুল নেই (এটি আমার অনুমানের অভাব যা আমার মনে হয় যে আমার বিরক্তির কারণ!)
monojohnny

@ মোমোজনহ্নি ক্ষমা প্রার্থনা করেছেন, তবে এটা খুব খারাপ যে
ডাউনভোটটি

উত্তর:


5

জিএইচসি SPECIALIZEএকটি টাইপ-শ্রেণীর উদাহরণ ঘোষণার জন্য একটি বিকল্পও দেয় । আমি Foo.hsনিম্নলিখিতটি প্রেরণ করে (প্রসারিত) কোড দিয়ে এটি চেষ্টা করেছি :

instance (Num r, V.Vector v r, Factored m r) => Num (VT v m r) where 
    {-# SPECIALIZE instance ( Factored m Int => Num (VT U.Vector m Int)) #-}
    VT x + VT y = VT $ V.zipWith (+) x y

যদিও এই পরিবর্তনটি পছন্দসই গতি অর্জন করতে পারেনি। কর্মক্ষমতা উন্নতি কী অর্জন করেছে তা হ'ল ম্যানুয়ালিVT U.Vector m Int একই ফাংশন সংজ্ঞা সহ টাইপের জন্য একটি বিশেষ উদাহরণ যুক্ত করা হয়েছিল :

instance (Factored m Int) => Num (VT U.Vector m Int) where 
    VT x + VT y = VT $ V.zipWith (+) x y

এর জন্য অ্যাডিং OverlappingInstancesএবং FlexibleInstancesইন করা দরকার LANGUAGE

মজার বিষয় হল, উদাহরণস্বরূপ প্রোগ্রামটিতে, ওভারল্যাপিংয়ের উদাহরণ সহ প্রাপ্ত স্পিডআপটি আপনি সমস্ত SPECIALIZEএবং মুছে ফেলা সত্ত্বেও রয়ে যায়INLINABLE স্পিডআপটি প্রাগমা ফেললেও অবশেষ।


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