আর এ লুপ অপারেশন গতি


193

আমি আর আমি একটি বড় কর্মক্ষমতা সমস্যা হল একটি ওভার iterates একটি ফাংশন লিখেছিলেন আছে data.frameঅবজেক্ট। এটি কেবল একটিতে একটি নতুন কলাম যুক্ত করে data.frameএবং কিছু জমা করে। (সাধারণ অপারেশন)। data.frameমোটামুটিভাবে 850K সারি হয়েছে। আমার পিসি এখনও কাজ করছে (এখন প্রায় 10 ঘন্টা) এবং রানটাইম সম্পর্কে আমার কোনও ধারণা নেই।

dayloop2 <- function(temp){
    for (i in 1:nrow(temp)){    
        temp[i,10] <- i
        if (i > 1) {             
            if ((temp[i,6] == temp[i-1,6]) & (temp[i,3] == temp[i-1,3])) { 
                temp[i,10] <- temp[i,9] + temp[i-1,10]                    
            } else {
                temp[i,10] <- temp[i,9]                                    
            }
        } else {
            temp[i,10] <- temp[i,9]
        }
    }
    names(temp)[names(temp) == "V10"] <- "Kumm."
    return(temp)
}

এই ধারণাটি কীভাবে কার্যকর করা যায়?

উত্তর:


434

সবচেয়ে বড় সমস্যা এবং অকার্যকরতার মূলটি হ'ল ডেটা.ফ্রেমকে সূচীকরণ করা, আমি বোঝাতে চাইছি আপনি যেখানে ব্যবহার করেন এই সমস্ত লাইন temp[,]
এটি যথাসম্ভব এড়াতে চেষ্টা করুন। আমি আপনার ফাংশন নিয়েছি, সূচী পরিবর্তন এবং এখানে সংস্করণ_আ

dayloop2_A <- function(temp){
    res <- numeric(nrow(temp))
    for (i in 1:nrow(temp)){    
        res[i] <- i
        if (i > 1) {             
            if ((temp[i,6] == temp[i-1,6]) & (temp[i,3] == temp[i-1,3])) { 
                res[i] <- temp[i,9] + res[i-1]                   
            } else {
                res[i] <- temp[i,9]                                    
            }
        } else {
            res[i] <- temp[i,9]
        }
    }
    temp$`Kumm.` <- res
    return(temp)
}

আপনি দেখতে পাচ্ছেন যে আমি ভেক্টর তৈরি করেছি resযা ফলাফল সংগ্রহ করে। শেষে আমি এটিকে যুক্ত data.frameকরব এবং নামগুলির সাথে আমার গণ্ডগোলের দরকার নেই। তাহলে এটি কতটা ভাল?

আমি একে ফাংশন চালানোর data.frameসঙ্গে nrow1000 থেকে 1000 দ্বারা 10,000 প্রয়োজন এবং সঙ্গে সময় পরিমাপsystem.time

X <- as.data.frame(matrix(sample(1:10, n*9, TRUE), n, 9))
system.time(dayloop2(X))

ফলাফল হয়

কর্মক্ষমতা

আপনি দেখতে পাচ্ছেন যে আপনার সংস্করণটি দ্রুত থেকে নির্ভর করে nrow(X)। পরিবর্তিত সংস্করণটির লিনিয়ার সম্পর্ক রয়েছে এবং সাধারণ lmমডেলটি অনুমান করে যে 850,000 সারিগুলির জন্য গণনা 6 মিনিট 10 সেকেন্ড সময় নেয় takes

ভেক্টরাইজেশন শক্তি

শেন এবং ক্যালিমো যেহেতু তাদের জবাব দেয় ভেক্টরাইজেশন আরও ভাল পারফরম্যান্সের মূল চাবিকাঠি। আপনার কোড থেকে আপনি লুপের বাইরে যেতে পারেন:

  • কন্ডিশনার
  • ফলাফলের সূচনা (যা হ'ল temp[i,9])

এটি এই কোড বাড়ে

dayloop2_B <- function(temp){
    cond <- c(FALSE, (temp[-nrow(temp),6] == temp[-1,6]) & (temp[-nrow(temp),3] == temp[-1,3]))
    res <- temp[,9]
    for (i in 1:nrow(temp)) {
        if (cond[i]) res[i] <- temp[i,9] + res[i-1]
    }
    temp$`Kumm.` <- res
    return(temp)
}

এই ফাংশনগুলির জন্য ফলাফলের তুলনা করুন, এবার nrow10,000 থেকে 10,000 করে 10,000 করে।

কর্মক্ষমতা

টিউন করা সুর

আরেকটি ত্বক হ'ল একটি লুপকে ইনডেক্সিংয়ে পরিবর্তন temp[i,9]করা res[i](যা আই-ত্র লুপ পুনরাবৃত্তিতে ঠিক একই)। এটি আবার একটি ভেক্টরকে সূচীকরণ এবং একটি সূচকের মধ্যে পার্থক্য data.frame
দ্বিতীয় জিনিস: আপনি যখন লুপটি দেখেন তখন আপনি দেখতে পাবেন যে সমস্তর উপর লুপ করার দরকার নেই i, তবে কেবল সেই অবস্থার জন্য উপযুক্ত।
সুতরাং এখানে আমরা যেতে

dayloop2_D <- function(temp){
    cond <- c(FALSE, (temp[-nrow(temp),6] == temp[-1,6]) & (temp[-nrow(temp),3] == temp[-1,3]))
    res <- temp[,9]
    for (i in (1:nrow(temp))[cond]) {
        res[i] <- res[i] + res[i-1]
    }
    temp$`Kumm.` <- res
    return(temp)
}

পারফরম্যান্স যা আপনি অত্যন্ত অর্জন করেন তা কোনও ডেটা স্ট্রাকচারের উপর নির্ভর করে। অবিকল - TRUEশর্তের মানের শতাংশের উপরে । আমার সিমুলেটেড ডেটার জন্য এটি এক সেকেন্ডের নিচে 850,000 সারিগুলির জন্য গণনার সময় নেয়।

কর্মক্ষমতা

আমি চাই আপনি আরও যেতে পারেন, আমি কমপক্ষে দুটি জিনিস যা করতে পারি তা দেখতে পাচ্ছি:

  • Cশর্তসাপেক্ষ cumsum করতে একটি কোড লিখুন
  • যদি আপনি জানেন যে আপনার ডেটা সর্বাধিক সিকোয়েন্স বড় নয় তবে আপনি লুপটি ভেক্টরাইজড অবস্থায় পরিবর্তন করতে পারবেন, এমন কিছু

    while (any(cond)) {
        indx <- c(FALSE, cond[-1] & !cond[-n])
        res[indx] <- res[indx] + res[which(indx)-1]
        cond[indx] <- FALSE
    }

কোড সিমিউলেশন ও পরিসংখ্যান জন্য ব্যবহার করা হয় GitHub থেকে পাওয়া


2
যেহেতু আমি মারেককে গোপনে জিজ্ঞাসার কোনও উপায় খুঁজে পাচ্ছি না, কীভাবে এই গ্রাফগুলি তৈরি করা হয়েছিল?
কার্বন্টভেলভে

আপনি কি ডেটা বা প্লট সম্পর্কে জিজ্ঞাসা করছেন? জাল প্যাকেজ দিয়ে প্লট তৈরি করা হয়েছিল। আমি যদি সময় পাই তবে কোডটি ওয়েবে কোথাও রেখে আমি আপনাকে বিজ্ঞপ্তি দেব।
মারেক

@ কার্বন্টভেলভে উফস, আমি ভুল করেছিলাম :) এটি স্ট্যান্ডার্ড প্লট (বেস আর থেকে)।
মারেক

@ গ্রেগর দুর্ভাগ্যক্রমে না। এটি ক্রমযুক্ত যা আপনি এটি ভেক্টরাইজ করতে পারবেন না। সরল উদাহরণ: res = c(1,2,3,4)এবং condসব TRUE, তারপর চূড়ান্ত ফলাফল হওয়া উচিত: 1, 3(কারণ 1+2), 6(কারণ দ্বিতীয় এখন 3ও তৃতীয় হয় 3এছাড়াও), 10( 6+4)। সহজ সঙ্কলন আপনি পেয়েছেন করছেন 1, 3, 5, 7
মেরেক 25'16

আহ, আমার আরও যত্ন সহকারে চিন্তা করা উচিত ছিল। আমাকে ভুল দেখানোর জন্য ধন্যবাদ।
গ্রেগর থমাস

132

আর কোড দ্রুত করার জন্য সাধারণ কৌশল

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

একবার আপনি যদি বাধাটি বের করেন তবে আপনি যা চান তার জন্য আরও দক্ষ অ্যালগরিদমগুলি সম্পর্কে ভাবুন । সম্ভব হলে গণনাগুলি একবার চালানো উচিত, তাই:

আরও দক্ষ ফাংশন ব্যবহার করা মাঝারি বা বড় গতির লাভ করতে পারে। উদাহরণস্বরূপ, paste0একটি সামান্য দক্ষতা লাভ .colSums()উত্পাদন করে এবং তার আত্মীয়স্বজন কিছুটা আরও সুস্পষ্ট লাভ উত্পাদন করে। meanহয় বিশেষ করে ধীর

তারপরে আপনি কিছু সাধারণ সমস্যা এড়াতে পারেন :

  • cbind আপনাকে সত্যিই দ্রুত হ্রাস করবে।
  • আপনার ডেটা স্ট্রাকচারগুলি শুরু করুন, তারপরে এগুলি প্রতিবার প্রসারিত করার পরিবর্তে পূরণ করুন ।
  • এমনকি প্রাক-বরাদ্দ থাকা সত্ত্বেও, আপনি পাস-বাই-ভ্যালু পদ্ধতির পরিবর্তে একটি পাস-বাই-রেফারেন্স পদ্ধতির স্যুইচ করতে পারেন, তবে এটি ঝামেলার উপযুক্ত হবে না।
  • কটাক্ষপাত আর নরক এড়াতে আরো ফাঁদ জন্য।

আরও ভাল ভেক্টরাইজেশনের জন্য চেষ্টা করুন , যা প্রায়শই কিন্তু সর্বদা সহায়তা করতে পারে না। এই ক্ষেত্রে, অন্তর্নিহিতভাবে ভেক্টরাইজড কমান্ডগুলি পছন্দ করে ifelse, diffএবং এর মতো applyআদেশগুলি পরিবারের চেয়ে আরও উন্নতি প্রদান করে (যা একটি লিখিত লুপের উপর কোনও গতি বাড়িয়ে দেয় না)।

আপনি আর ফাংশনগুলিতে আরও তথ্য সরবরাহ করার চেষ্টা করতে পারেন । উদাহরণস্বরূপ, vapplyপরিবর্তেsapply ব্যবহার করুন colClassesএবং পাঠ্য-ভিত্তিক ডেটা পড়ার সময় নির্দিষ্ট করুন । আপনি কতটা অনুমান করেন তা নির্ভর করে গতি লাভগুলি পরিবর্তনশীল হবে।

এরপরে, অনুকূলিত প্যাকেজগুলি বিবেচনা করুন : data.tableপ্যাকেজটি ডেটা ম্যানিপুলেশন এবং বিপুল পরিমাণে ডেটা পড়ার ক্ষেত্রে, যেখানে এটির ব্যবহার সম্ভব সেখানে প্রচুর গতি লাভ করতে পারে fread

এরপরে আর কল করার আরও দক্ষ পদ্ধতির মাধ্যমে গতি অর্জনের চেষ্টা করুন :

  • আপনার আর স্ক্রিপ্টটি সংকলন করুন। অথবা সুনির্দিষ্ট সময়ে সংকলনের জন্য কনসার্টে Raএবং jitপ্যাকেজগুলি ব্যবহার করুন (ডার্কের এই উপস্থাপনায় একটি উদাহরণ রয়েছে )।
  • নিশ্চিত করুন যে আপনি একটি অনুকূলিত BLAS ব্যবহার করছেন। এই বোর্ড জুড়ে গতি লাভ প্রদান করে। সত্যিই, এটি লজ্জার বিষয় যে আর-ই স্বয়ংক্রিয়ভাবে ইনস্টল করার ক্ষেত্রে সবচেয়ে কার্যকর লাইব্রেরি ব্যবহার করে না। আশা করি বিপ্লব আর তারা এখানে যে কাজটি করেছে তা পুরো সম্প্রদায়কে ফিরিয়ে দেবে।
  • র‌্যাডফোর্ড নীল একগুচ্ছ অপ্টিমাইজেশান করেছে, যার মধ্যে কিছুগুলি আর কোরে গৃহীত হয়েছিল, এবং আরও অনেককে পিকিআর-এ পরিণত হয়েছিল

এবং সবশেষে, যদি উপরের সমস্তগুলি এখনও আপনার প্রয়োজনের মতো দ্রুত না পায় তবে ধীর কোড স্নিপেটের জন্য আপনার একটি দ্রুত ভাষায় যেতে হবে । Rcppএবং inlineএখানে সংমিশ্রণটি সি ++ কোডের সাথে অ্যালগরিদমের কেবল সবচেয়ে ধীরতম অংশটি প্রতিস্থাপন করে। এখানে, উদাহরণস্বরূপ, এটি করার ক্ষেত্রে আমার প্রথম প্রচেষ্টা এবং এটি অত্যন্ত উচ্চতর অপ্টিমাইজড আর সমাধানগুলিও উড়িয়ে দেয়।

যদি আপনি এত কিছুর পরেও সমস্যায় পড়ে যান তবে আপনার আরও কম্পিউটারের শক্তি প্রয়োজন। দেখব parallelization ( http://cran.r-project.org/web/views/HighPerformanceComputing.html ) অথবা এমনকি জিপিইউ-ভিত্তিক সমাধান ( gpu-tools)।

অন্যান্য নির্দেশিকা লিঙ্ক


35

আপনি যদি forলুপগুলি ব্যবহার করেন তবে আপনি সম্ভবত আর কোডিং করছেন যেন এটি সি বা জাভা বা অন্য কিছু। সঠিকভাবে ভেক্টোরাইজ করা আর কোড অত্যন্ত দ্রুত।

ধারাবাহিকভাবে 10,000 পূর্ণসংখ্যার একটি তালিকা তৈরি করতে কোডের এই দুটি সাধারণ বিট উদাহরণস্বরূপ নিন:

প্রথম কোড উদাহরণটি হ'ল কোনও কীভাবে একটি traditionalতিহ্যবাহী কোডিং দৃষ্টান্ত ব্যবহার করে একটি লুপ কোড করবেন। এটি সম্পূর্ণ হতে 28 সেকেন্ড সময় নেয়

system.time({
    a <- NULL
    for(i in 1:1e5)a[i] <- i
})
   user  system elapsed 
  28.36    0.07   28.61 

প্রাক বরাদ্দ মেমরির সহজ ক্রিয়া দ্বারা আপনি প্রায় 100 গুণ উন্নতি পেতে পারেন:

system.time({
    a <- rep(1, 1e5)
    for(i in 1:1e5)a[i] <- i
})

   user  system elapsed 
   0.30    0.00    0.29 

কিন্তু কোলন অপারেটরটি ব্যবহার করে বেস আর ভেক্টর অপারেশন ব্যবহার করা :এই অপারেশনটি কার্যত তাত্ক্ষণিক:

system.time(a <- 1:1e5)

   user  system elapsed 
      0       0       0 

+1 যদিও আমি আপনার দ্বিতীয় উদাহরণটিকে a[i]পরিবর্তন না করাকে অবিশ্বাস্য হিসাবে বিবেচনা করব । তবে system.time({a <- NULL; for(i in 1:1e5){a[i] <- 2*i} }); system.time({a <- 1:1e5; for(i in 1:1e5){a[i] <- 2*i} }); system.time({a <- NULL; a <- 2*(1:1e5)})এর একই ফল রয়েছে।
হেনরি

@ হেনরি, নিখুঁত মন্তব্য, তবে আপনি যেমন উল্লেখ করেছেন, ফলাফলগুলি একই are আমি এটিকে শুরু করার জন্য উদাহরণটি সংশোধন করেছি rep(1, 1e5)- সময়গুলি অভিন্ন।
অ্যান্ড্রি

17

সূচকগুলি বা নেস্টেড ifelse()স্টেটমেন্ট ব্যবহার করে লুপগুলি এড়িয়ে গিয়ে এটি আরও দ্রুত তৈরি করা যেতে পারে ।

idx <- 1:nrow(temp)
temp[,10] <- idx
idx1 <- c(FALSE, (temp[-nrow(temp),6] == temp[-1,6]) & (temp[-nrow(temp),3] == temp[-1,3]))
temp[idx1,10] <- temp[idx1,9] + temp[which(idx1)-1,10] 
temp[!idx1,10] <- temp[!idx1,9]    
temp[1,10] <- temp[1,9]
names(temp)[names(temp) == "V10"] <- "Kumm."

উত্তর করার জন্য ধন্যবাদ. আমি আপনার বক্তব্য বুঝতে চেষ্টা করি। লাইন 4: "টেম্প [idx1,10] <- টেম্প [idx1,9] + টেম্প [যা (idx1) -1,10]" একটি ত্রুটি ঘটায় কারণ দীর্ঘ বস্তুর দৈর্ঘ্য দৈর্ঘ্যের একাধিক নয় সংক্ষিপ্ত অবজেক্ট "টেম্প [idx1,9] = সংখ্যা [1: 11496]" এবং "টেম্প [যা (idx1) -1,10] = অব [1: 11494]" সুতরাং 2 টি সারি অনুপস্থিত।
কে

যদি আপনি কোনও ডেটা নমুনা সরবরাহ করেন (কয়েকটি সারি সহ ডুপুট (ব্যবহার করুন) তবে আমি এটি আপনার জন্য ঠিক করব। যার () - 1 বিটের কারণে সূচকগুলি অসম। তবে আপনার দেখতে হবে এটি এখান থেকে কীভাবে কাজ করে: কোনও লুপিং বা প্রয়োগের প্রয়োজন নেই; শুধু ভেক্টরাইজড ফাংশন ব্যবহার করুন।
শেন

1
কি দারুন! আমি সবেমাত্র নেস্টেড if..else ফাংশন ব্লক এবং ম্যাপলি করে নেস্টেড ifelse ফাংশনে পরিবর্তন করেছি এবং 200x স্পিডআপ পেয়েছি!
জেমস

আপনার সাধারণ পরামর্শটি যথাযথ, তবে iকোডটিতে আপনি সত্যটি মিস করেছেন, যে- মানটি -২০ এর উপর নির্ভর করে i-1যাতে আপনার এটি (ব্যবহার করে which()-1) সেভাবে সেট করা যায় না ।
মেরেক

8

আমি পুনর্লিখনের কোডটি অপছন্দ করি ... অবশ্যই ইফলেস এবং ল্যাপলি আরও ভাল বিকল্প তবে কখনও কখনও এটি ফিট করা শক্ত হয় is

আমি প্রায়শই ডাটা.ফ্রেমগুলি ব্যবহার করি যেমন একটি যেমন তালিকাগুলি ব্যবহার করে df$var[i]

এখানে একটি তৈরি উদাহরণ:

nrow=function(x){ ##required as I use nrow at times.
  if(class(x)=='list') {
    length(x[[names(x)[1]]])
  }else{
    base::nrow(x)
  }
}

system.time({
  d=data.frame(seq=1:10000,r=rnorm(10000))
  d$foo=d$r
  d$seq=1:5
  mark=NA
  for(i in 1:nrow(d)){
    if(d$seq[i]==1) mark=d$r[i]
    d$foo[i]=mark
  }
})

system.time({
  d=data.frame(seq=1:10000,r=rnorm(10000))
  d$foo=d$r
  d$seq=1:5
  d=as.list(d) #become a list
  mark=NA
  for(i in 1:nrow(d)){
    if(d$seq[i]==1) mark=d$r[i]
    d$foo[i]=mark
  }
  d=as.data.frame(d) #revert back to data.frame
})

ডেটা.ফ্রেম সংস্করণ:

   user  system elapsed 
   0.53    0.00    0.53

তালিকা সংস্করণ:

   user  system elapsed 
   0.04    0.00    0.03 

ডেটা.ফ্রেমের চেয়ে ভেক্টরের একটি তালিকা ব্যবহার করতে 17x গুণ দ্রুত।

কেন অভ্যন্তরীণভাবে ডেটা.ফ্রেমগুলি এ বিষয়ে এত ধীর? কেউ ভাবেন যে তারা তালিকার মতো কাজ করে ...

এমনকি আরও দ্রুত কোডের class(d)='list'জন্য d=as.list(d)এবং এর পরিবর্তে এটি করুনclass(d)='data.frame'

system.time({
  d=data.frame(seq=1:10000,r=rnorm(10000))
  d$foo=d$r
  d$seq=1:5
  class(d)='list'
  mark=NA
  for(i in 1:nrow(d)){
    if(d$seq[i]==1) mark=d$r[i]
    d$foo[i]=mark
  }
  class(d)='data.frame'
})
head(d)

1
এটি সম্ভবত ওভারহেডকে ধন্যবাদ জানায় [<-.data.frame, যা আপনি যখন করেন তখন কোনওভাবে বলা হয় d$foo[i] = markএবং প্রতিটি <-সংশোধনীর ক্ষেত্রে সম্ভবত সম্পূর্ণ ডেটা ফ্রেম এর ভেক্টরের একটি নতুন অনুলিপি তৈরি করা শেষ হতে পারে । এটি এসও সম্পর্কে একটি আকর্ষণীয় প্রশ্ন করবে।
ফ্রাঙ্ক

2
@ ফ্র্যাঙ্ক ইট (i) এটি নিশ্চিত করতে হবে যে পরিবর্তিত বস্তুটি এখনও একটি বৈধ ডেটা f ফ্রেম এবং (ii) আফাইক সম্ভবত কমপক্ষে একটি অনুলিপি তৈরি করে। ডেটাফ্রেম সাবসাইনমেন্টটি ধীর গতির হিসাবে পরিচিত এবং আপনি যদি দীর্ঘ উত্সের কোডটি দেখেন এটি সত্যি অবাক হওয়ার মতো নয়।
রোল্যান্ড

@ ফ্র্যাঙ্ক, @ রোল্যান্ড: df$var[i]স্বরলিপি কি একই [<-.data.frameকাজ করে? আমি লক্ষ করেছি এটি আসলেই বেশ দীর্ঘ। যদি তা না হয় তবে এটি কোন ফাংশনটি ব্যবহার করে?
ক্রিস

@ ক্রিস আমি বিশ্বাস করি যে d$foo[i]=markপ্রায় অনূদিত হয় d <- `$<-`(d, 'foo', `[<-`(d$foo, i, mark))তবে কিছু অস্থায়ী ভেরিয়েবল ব্যবহার করে।
টিম গুডম্যান

7

যেমন আরি তার উত্তরের শেষে উল্লেখ করেছেন, প্যাকেজগুলি Rcppএবং inlineপ্যাকেজগুলি জিনিসগুলি দ্রুত করা অবিশ্বাস্যরকম সহজ করে তোলে। উদাহরণস্বরূপ, এই inlineকোডটি চেষ্টা করুন (সতর্কতা: পরীক্ষা করা হয়নি):

body <- 'Rcpp::NumericMatrix nm(temp);
         int nrtemp = Rccp::as<int>(nrt);
         for (int i = 0; i < nrtemp; ++i) {
             temp(i, 9) = i
             if (i > 1) {
                 if ((temp(i, 5) == temp(i - 1, 5) && temp(i, 2) == temp(i - 1, 2) {
                     temp(i, 9) = temp(i, 8) + temp(i - 1, 9)
                 } else {
                     temp(i, 9) = temp(i, 8)
                 }
             } else {
                 temp(i, 9) = temp(i, 8)
             }
         return Rcpp::wrap(nm);
        '

settings <- getPlugin("Rcpp")
# settings$env$PKG_CXXFLAGS <- paste("-I", getwd(), sep="") if you want to inc files in wd
dayloop <- cxxfunction(signature(nrt="numeric", temp="numeric"), body-body,
    plugin="Rcpp", settings=settings, cppargs="-I/usr/include")

dayloop2 <- function(temp) {
    # extract a numeric matrix from temp, put it in tmp
    nc <- ncol(temp)
    nm <- dayloop(nc, temp)
    names(temp)[names(temp) == "V10"] <- "Kumm."
    return(temp)
}

#includeআইংগুলির জন্য একই পদ্ধতি রয়েছে , যেখানে আপনি কেবল একটি প্যারামিটারটি পাস করেন

inc <- '#include <header.h>

cxxfunction, হিসাবে include=inc। এ সম্পর্কে সত্যিই দুর্দান্ত যা এটি আপনার জন্য সমস্ত লিঙ্কিং এবং সংকলন করে, তাই প্রোটোটাইপিংটি খুব দ্রুত।

দাবি অস্বীকার: আমি পুরোপুরি নিশ্চিত নই যে টেম্প্পের ক্লাসটি সংখ্যাসূচক হওয়া উচিত এবং সংখ্যার ম্যাট্রিক্স বা অন্য কিছু নয়। তবে আমি বেশিরভাগ নিশ্চিত

সম্পাদনা করুন: এর পরেও যদি আপনার আরও বেশি গতির প্রয়োজন হয় তবে ওপেনএমপি একটি সমান্তরালনের সুবিধা C++। আমি এটি থেকে ব্যবহার করার চেষ্টা করি নি inline, তবে এটি কাজ করা উচিত। ধারণাটি হবে, nকোরগুলির ক্ষেত্রে লুপের পুনরাবৃত্তিটি kচালিত করা উচিত k % n। ম্যাটলফের আর্ট অফ আর প্রোগ্রামিং- এ একটি উপযুক্ত পরিচয় পাওয়া গেছে , যা এখানে পাওয়া যায় , ১ chapter তম অধ্যায়ে, সি অবলম্বনে


3

উত্তর এখানে দুর্দান্ত। একটি ছোটখাটো দিক covered াকেনি যে প্রশ্নটিটি " আমার পিসি এখনও কাজ করছে (এখন প্রায় 10 ঘন্টা) এবং রানটাইম সম্পর্কে আমার কোনও ধারণা নেই "। পরিবর্তনগুলি কীভাবে গতিকে প্রভাবিত করে এমনটি বোধ করার জন্য এবং এটি সম্পূর্ণ হতে কতটা সময় নিবে তা নিরীক্ষণের জন্য বোধ করার জন্য বিকাশ করার সময় আমি সর্বদা নীচের কোডগুলিকে লুপগুলিতে রাখি।

dayloop2 <- function(temp){
  for (i in 1:nrow(temp)){
    cat(round(i/nrow(temp)*100,2),"%    \r") # prints the percentage complete in realtime.
    # do stuff
  }
  return(blah)
}

পাশাপাশি lapply সঙ্গে কাজ করে।

dayloop2 <- function(temp){
  temp <- lapply(1:nrow(temp), function(i) {
    cat(round(i/nrow(temp)*100,2),"%    \r")
    #do stuff
  })
  return(temp)
}

লুপের মধ্যে ফাংশনটি যদি খুব দ্রুত হয় তবে লুপের সংখ্যাটি বড় হয় তবে কনসোলে প্রিন্টিংয়ের একটি ওভারহেড থাকায় প্রতিটি প্রায়শই মুদ্রণ বিবেচনা করুন। যেমন

dayloop2 <- function(temp){
  for (i in 1:nrow(temp)){
    if(i %% 100 == 0) cat(round(i/nrow(temp)*100,2),"%    \r") # prints every 100 times through the loop
    # do stuff
  }
  return(temp)
}

অনুরূপ বিকল্প, ভগ্নাংশটি i / n মুদ্রণ করুন। আমার সর্বদা এমন কিছু থাকে cat(sprintf("\nNow running... %40s, %s/%s \n", nm[i], i, n))যেহেতু আমি সাধারণত নামযুক্ত জিনিসগুলি (নামগুলির সাথে nm) লুপ করি ।
ফ্রাঙ্ক

2

আর এ, আপনি প্রায়শই applyপারিবারিক ফাংশনগুলি ব্যবহার করে লুপ প্রসেসিং দ্রুত করতে পারবেন (আপনার ক্ষেত্রে এটি সম্ভবত হবে replicate)। plyrঅগ্রগতি বার সরবরাহ করে এমন প্যাকেজটি একবার দেখুন ।

অন্য বিকল্পটি সম্পূর্ণরূপে লুপগুলি এড়ানো এবং ভেক্টরাইজড গাণিতিকগুলির সাথে তাদের প্রতিস্থাপন করা। আপনি ঠিক কী করছেন তা আমি নিশ্চিত নই, তবে আপনি সম্ভবত আপনার ফাংশনটি সমস্ত সারিতে একবারে প্রয়োগ করতে পারেন:

temp[1:nrow(temp), 10] <- temp[1:nrow(temp), 9] + temp[0:(nrow(temp)-1), 10]

এটি অনেক বেশি দ্রুত হবে এবং তারপরে আপনি নিজের অবস্থার সাথে সারিগুলি ফিল্টার করতে পারবেন:

cond.i <- (temp[i, 6] == temp[i-1, 6]) & (temp[i, 3] == temp[i-1, 3])
temp[cond.i, 10] <- temp[cond.i, 9]

ভেক্টরাইজড গাণিতিকগুলির আরও বেশি সময় প্রয়োজন এবং সমস্যাটি সম্পর্কে চিন্তাভাবনা করা প্রয়োজন তবে আপনি কখনও কখনও মৃত্যুদন্ডের সময়কালের কয়েকটি ক্রম সংরক্ষণ করতে পারেন।


14
আপনি যে ভেক্টর ফাংশনগুলিতে স্পট করছেন তা লুপের চেয়ে দ্রুত হবে বা প্রয়োগ হবে () তবে এটি সত্য নয় যে প্রয়োগ () লুপের চেয়েও দ্রুত। অনেক ক্ষেত্রে প্রয়োগ () কেবল ব্যবহারকারী থেকে লুপ দূরে সরানো হয় তবে লুপিং করে। পূর্ববর্তী এই প্রশ্নটি দেখুন: স্ট্যাকওভারফ্লো.com
জেডি লং

0

এর সাথে প্রক্রিয়াজাতকরণ data.tableএকটি কার্যকর বিকল্প:

n <- 1000000
df <- as.data.frame(matrix(sample(1:10, n*9, TRUE), n, 9))
colnames(df) <- paste("col", 1:9, sep = "")

library(data.table)

dayloop2.dt <- function(df) {
  dt <- data.table(df)
  dt[, Kumm. := {
    res <- .I;
    ifelse (res > 1,             
      ifelse ((col6 == shift(col6, fill = 0)) & (col3 == shift(col3, fill = 0)) , 
        res <- col9 + shift(res)                   
      , # else
        res <- col9                                 
      )
     , # else
      res <- col9
    )
  }
  ,]
  res <- data.frame(dt)
  return (res)
}

res <- dayloop2.dt(df)

m <- microbenchmark(dayloop2.dt(df), times = 100)
#Unit: milliseconds
#       expr      min        lq     mean   median       uq      max neval
#dayloop2.dt(df) 436.4467 441.02076 578.7126 503.9874 575.9534 966.1042    10

আপনি যদি শর্ত ফিল্টারিংয়ের সম্ভাব্য লাভগুলি উপেক্ষা করেন তবে এটি খুব দ্রুত। স্পষ্টতই, আপনি যদি ডেটার উপসেটটিতে গণনা করতে পারেন তবে এটি সহায়তা করে।


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