در مورد زبانهای سطح بالایی مثل R یا متلب، همیشه توصیه میشه که از قابلیتهای built-in استفاده کنید. مثلا فرض کنید میخوایم ضرب داخلی دو بردار با طول مساوی رو پیادهسازی کنیم. اول بگم که ضرب داخلی برای دو بردار همطول و برابر با مجموع ضرب عضوهای نظیر تعریف میشه. حالا برای اینکار به شکل معمول داریم:
x = c(1,2,5) y= c(5,3,1) sum(x*y)
و خروجی به شکل:
به دست میاد. اما خیلی وقتا میخوایم کاری انجام بدیم که بهطور طبیعی با اعمال داخلی R قابل انجام نیست. یعنی نمیشه به شکل برداری نوشتشون. اونوقت لازمه از روشهای تکراری مثل حلقهی for یا while استفاده کنیم:
output = 0 for (i in c(1:3)){ output = output + x[i] * y[i] }
اما استفاده از for در زبانهای سطح بالا به هیچوجه کار بهینهای نیست. و سرعت اجرای برای دادههای بزرگتر توی اونا بهشدت کمه و ممکنه شما رو برای حجم زیاد دادهها ناکام بذاره.
خب چه میشه کرد؟
بذارین این سوال رو با یه سوال دیگه هم روبرو کنیم. پکیجهای R رو که گاها پر از الگوریتمای پیچیده است و نمیشه بهراحتی برداری کرد و پیادهسازیشون نیاز به استفاده از مواردی مثل حلقههای for داره رو چطور پیادهسازی میکنن که اینقدر سریع اجرا میشن.
جواب اینه که پکیجهای R عمدتا با c++ و fortran نوشته میشن و توی R به شکل shared object استفاده میشن.
چطور میتونیم خودمون این کارو بکنیم؟
خیلی ساده است. با استفاده از پکیج Rcpp توی R میشود کد c++ رو برای R کامپایل کرد. برای استفاده از این پکیج اول اونو نصب میکنیم:
install.packages('Rcpp')
به همین سادگی. حالا شما این بسته رو که فراخوانی کنید میتونید ازش استفاده کنید و به کمکش کد c++تون رو کامپایل کنید و استفاده کنید:
library('Rcpp')
برای مثال:
library(Rcpp) cppFunction( "int test(NumericVector X, NumericVector Y){ int len = X.size(); int output = 0; for (int i=0; i<len; i++){ output += X[i] * Y[i]; } return (output); }") test(x,y)
و خروجی برابر همون مقدار 16 خواهد بود. اما اینبار با سرعت اجرای بالاتر از forهای R.
همین کار رو میتونید تو یه فایل جدا انجامش بدید و با دستور sourceCpp فراخوانیش کنید.
در کل این پکیج بیشتر از یه پست وبلاگی زمانبره و توصیه میکنم داکیومنتهای این پکیج رو بخونید و یه نگاهی هم به مثالها بندازید.
همواره اگه اصلاحی برا نوشتههای من دارید خوشحال میشم ببینم.