ডেটা টেবিলটি ফিল্টার করার সময় অ্যান্ডিংয়ের ওপরে চেইন করার পারফরম্যান্স সুবিধা


12

আমি একই ধরণের কাজগুলি একক লাইনে একসাথে করে ফেলার অভ্যাসে আছি। উদাহরণস্বরূপ, যদি আমি ফিল্টার করতে প্রয়োজন a, bএবং cএকটি ডাটা টেবিলে, আমি তাদের একসঙ্গে এক রেখে দেব []ANDs না সঙ্গে। গতকাল, আমি লক্ষ্য করেছি যে আমার বিশেষ ক্ষেত্রে এটি পরিবর্তে অবিশ্বাস্যরূপে ধীর এবং পরীক্ষিত চেইন ফিল্টার ছিল। আমি নীচে একটি উদাহরণ অন্তর্ভুক্ত করেছি।

প্রথমত, আমি এলোমেলো সংখ্যা জেনারেটর বীজ করি, লোড এবং একটি ডামি ডেটা সেট তৈরি করি।

# Set RNG seed
set.seed(-1)

# Load libraries
library(data.table)

# Create data table
dt <- data.table(a = sample(1:1000, 1e7, replace = TRUE),
                 b = sample(1:1000, 1e7, replace = TRUE),
                 c = sample(1:1000, 1e7, replace = TRUE),
                 d = runif(1e7))

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

# Chaining method
chain_filter <- function(){
  dt[a %between% c(1, 10)
     ][b %between% c(100, 110)
       ][c %between% c(750, 760)]
}

# Anding method
and_filter <- function(){
  dt[a %between% c(1, 10) & b %between% c(100, 110) & c %between% c(750, 760)]
}

এখানে, আমি পরীক্ষা করি তারা একই ফলাফল দেয়।

# Check both give same result
identical(chain_filter(), and_filter())
#> [1] TRUE

অবশেষে, আমি সেগুলি মানি।

# Benchmark
microbenchmark::microbenchmark(chain_filter(), and_filter())
#> Unit: milliseconds
#>            expr      min        lq      mean    median        uq       max
#>  chain_filter() 25.17734  31.24489  39.44092  37.53919  43.51588  78.12492
#>    and_filter() 92.66411 112.06136 130.92834 127.64009 149.17320 206.61777
#>  neval cld
#>    100  a 
#>    100   b

2019-10-25 এ ডিপেক্স প্যাকেজ (v0.3.0) দ্বারা তৈরি করা হয়েছে

এই ক্ষেত্রে, চেইন রান সময় প্রায় 70% হ্রাস করে। কেন এই ক্ষেত্রে? মানে, ডেটা টেবিলের ফণার নীচে কী চলছে? আমি ব্যবহারের বিরুদ্ধে কোনও সতর্কতা দেখিনি &, তাই আমি আশ্চর্য হয়েছি যে পার্থক্যটি এত বড়। উভয় ক্ষেত্রেই তারা একই শর্তের মূল্যায়ন করে, যাতে কোনও পার্থক্য হওয়া উচিত নয়। অ্যান্ড কেসের ক্ষেত্রে, &একটি দ্রুত অপারেটর এবং তারপরে এটি কেবল একবার ডেটা টেবিলটি ফিল্টার করতে হবে (যেমন, এএনএস থেকে প্রাপ্ত লজিকাল ভেক্টর ব্যবহার করে), শৃঙ্খলার ক্ষেত্রে তিনবার ফিল্টার করার বিপরীতে।

বোনাস প্রশ্ন

এই নীতিটি কি সাধারণভাবে ডেটা টেবিল অপারেশনের জন্য ধারণ করে? মডুলারাইজিং কাজগুলি কি সর্বদা আরও ভাল কৌশল?


1
আমি এই পর্যবেক্ষণটি একইভাবে, বিস্মিতও করেছি। আমার অভিজ্ঞতায় চেইন স্পিড পিক-আপ সাধারণ ক্রিয়াকলাপ জুড়ে লক্ষ্য করা যায়।
জেডিজি

9
যখন ডেটা.টিভলে এই জাতীয় ক্ষেত্রে কিছু অপ্টিমাইজেশন করে (এটি একা একটি কীর্তি এবং বেস উন্নত বনাম!), সাধারণভাবে এন্ড বি এবং সি & ডি ফলাফলগুলি সংযুক্ত করার আগে এবং ফিল্টার করার আগে সমস্ত এন লজিকাল অবস্থার সময় মূল্যায়ন করবে । যদিও ২ য় তৃতীয় এবং চতুর্থ লজিকাল কলগুলি কেবলমাত্র n বার মূল্যায়ন করা হয় (যেখানে এন <= N প্রতিটি শর্তের পরে থাকা সারিগুলির সংখ্যা)
মাইকেলচিরিকো

পছন্দ করুন তা অবাক! কেন জানি না, তবে আমি কেবল ধরে
নিয়েছিলাম

@ মাইকেলচিরিকোর মন্তব্য অনুসরণ করে, আপনি baseনিম্নলিখিতগুলি দিয়ে ভেক্টরগুলির সাথে অনুরূপ পর্যবেক্ষণ করতে পারেন : chain_vec <- function() { x <- which(a < .001); x[which(b[x] > .999)] }এবং and_vec <- function() { which(a < .001 & b > .999) }। (কোথা থেকে aএবং bএকই দৈর্ঘ্যের ভেক্টরগুলি runif- আমি n = 1e7এই কাট অফগুলির জন্য ব্যবহার করেছি )।
ClancyStats

@ মিশেলচিরিকো আহ, আমি দেখছি। সুতরাং, বড় পার্থক্যটি হ'ল চেইনের প্রতিটি ধাপে, ডাটা টেবিলটি যথেষ্ট পরিমাণে ছোট এবং অতএব শর্তটি মূল্যায়ন এবং ফিল্টার চালু করার জন্য তত দ্রুত? এটা বোধগম্য. আপনার অন্তর্দৃষ্টি জন্য ধন্যবাদ!
লিংগবাকর

উত্তর:


8

বেশিরভাগ ক্ষেত্রেই মন্তব্যগুলিতে উত্তরটি দেওয়া হয়েছিল: data.table"চেইন পদ্ধতি" এই ক্ষেত্রে "অ্যান্ডিং পদ্ধতি" এর চেয়ে দ্রুত, কারণ শৃঙ্খলা একের পর এক শর্তগুলি চালায়। প্রতিটি পদক্ষেপের আকার হ্রাস করার data.tableসাথে সাথে পরবর্তীটির জন্য মূল্যায়ন কম হয়। "অ্যান্ডিং" প্রতিবার পূর্ণ আকারের ডেটার শর্তগুলির মূল্যায়ন করে।

আমরা এটি একটি উদাহরণ দিয়ে প্রমাণ করতে পারি: যখন পৃথক পদক্ষেপগুলি আকারের আকার হ্রাস না করে data.table(অর্থাত্ চেক করার শর্তগুলি উভয়ের মূল্যায়নের ক্ষেত্রে একই):

chain_filter <- function(){
  dt[a %between% c(1, 1000) # runs evaluation but does not filter out cases
     ][b %between% c(1, 1000)
       ][c %between% c(750, 760)]
}

# Anding method
and_filter <- function(){
  dt[a %between% c(1, 1000) & b %between% c(1, 1000) & c %between% c(750, 760)]
}

একই ডেটা ব্যবহার করে কিন্তু benchপ্যাকেজটি, যা ফলাফল অভিন্ন কিনা তা স্বয়ংক্রিয়ভাবে পরীক্ষা করে:

res <- bench::mark(
  chain = chain_filter(),
  and = and_filter()
)
summary(res)
#> # A tibble: 2 x 6
#>   expression      min   median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr> <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#> 1 chain         299ms    307ms      3.26     691MB     9.78
#> 2 and           123ms    142ms      7.18     231MB     5.39
summary(res, relative = TRUE)
#> # A tibble: 2 x 6
#>   expression   min median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr> <dbl>  <dbl>     <dbl>     <dbl>    <dbl>
#> 1 chain       2.43   2.16      1         2.99     1.82
#> 2 and         1      1         2.20      1        1

আপনি এখানে দেখতে পারেন ANDing পদ্ধতির 2,43 বার এই ক্ষেত্রে দ্রুততর । এর অর্থ শৃঙ্খলাবদ্ধতা আসলে কিছুটা ওভারহেড যুক্ত করে , যা সাধারণত এবং আঙ্গুলের দ্রুত হওয়া উচিত। যদি শর্তগুলিdata.table ধাপে ধাপের আকার হ্রাস করে তবেই ছাড়ুন । তাত্ত্বিকভাবে, চেইন পদ্ধতিটি এমনকি ধীর হতে পারে (এমনকি ওভারহেডটিও একপাশে রেখে), যদি কোনও শর্তের ফলে ডেটার আকার বাড়বে increase তবে কার্যত আমি মনে করি যে লজিকাল ভেক্টরগুলির পুনর্ব্যবহারের অনুমতি দেওয়া হয়নি সেহেতু এটি সম্ভব নয় data.table। আমি মনে করি এটি আপনার বোনাস প্রশ্নের উত্তর দেয়।

তুলনার জন্য, আমার মেশিনে মূল ফাংশনগুলি এর সাথে bench:

res <- bench::mark(
  chain = chain_filter_original(),
  and = and_filter_original()
)
summary(res)
#> # A tibble: 2 x 6
#>   expression      min   median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr> <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#> 1 chain        29.6ms   30.2ms     28.5     79.5MB     7.60
#> 2 and         125.5ms  136.7ms      7.32   228.9MB     7.32
summary(res, relative = TRUE)
#> # A tibble: 2 x 6
#>   expression   min median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr> <dbl>  <dbl>     <dbl>     <dbl>    <dbl>
#> 1 chain       1      1         3.89      1        1.04
#> 2 and         4.25   4.52      1         2.88     1
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.