অন্যান্য উত্তরগুলির মধ্যে কোনওটিতেই গতির পার্থক্যের প্রাথমিক কারণ উল্লেখ করা হয়নি, এটি হ'ল zipped
সংস্করণ 10,000 টি দ্বিগুণ বরাদ্দ এড়িয়ে চলে। অন্যান্য উত্তর একটি দম্পতি হিসাবে না নোট, zip
সংস্করণ যখন কোন মধ্যবর্তী অ্যারের জড়িত থাকে, zipped
সংস্করণ না, কিন্তু 10,000 উপাদানের জন্য একটি অ্যারের বণ্টন কি করে নয় zip
সংস্করণ এত খারাপ এটা 10,000 সংক্ষিপ্ত ছিলো tuples যে যে অ্যারে করা হচ্ছে। এগুলি JVM- তে অবজেক্ট দ্বারা প্রতিনিধিত্ব করা হয়, সুতরাং আপনি অবিলম্বে দূরে ফেলতে চলেছেন এমন জিনিসগুলির জন্য আপনি একগুচ্ছ অবজেক্ট বরাদ্দ করছেন।
এই উত্তরটির বাকী অংশটি আপনি কীভাবে এটি নিশ্চিত করতে পারবেন সে সম্পর্কে আরও কিছুটা বিশদে যায়।
ভাল বেঞ্চমার্কিং
আপনি সত্যিই jmh এর মতো একটি কাঠামো ব্যবহার করতে চান জেভিএম-তে জেভিএম-তে দায়িত্বপূর্ণভাবে কোনও ধরণের বেঞ্চমার্কিং করার জন্য এবং তারপরেও দায়িত্বশীলতার অংশটি শক্ত, যদিও জেএমএইচ সেটআপ খুব খারাপ নয় isn't আপনার যদি এর project/plugins.sbt
মতো থাকে:
addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.3.7")
এবং এর build.sbt
মতো একটি (আমি 2.11.8 ব্যবহার করছি যেহেতু আপনি উল্লেখ করছেন যে আপনি কী ব্যবহার করছেন):
scalaVersion := "2.11.8"
enablePlugins(JmhPlugin)
তারপরে আপনি নিজের মানদণ্ডটি এভাবে লিখতে পারেন:
package zipped_bench
import org.openjdk.jmh.annotations._
@State(Scope.Benchmark)
@BenchmarkMode(Array(Mode.Throughput))
class ZippedBench {
val arr1 = Array.fill(10000)(math.random)
val arr2 = Array.fill(10000)(math.random)
def ES(arr: Array[Double], arr1: Array[Double]): Array[Double] =
arr.zip(arr1).map(x => x._1 + x._2)
def ES1(arr: Array[Double], arr1: Array[Double]): Array[Double] =
(arr, arr1).zipped.map((x, y) => x + y)
@Benchmark def withZip: Array[Double] = ES(arr1, arr2)
@Benchmark def withZipped: Array[Double] = ES1(arr1, arr2)
}
এবং এটি দিয়ে চালান sbt "jmh:run -i 10 -wi 10 -f 2 -t 1 zipped_bench.ZippedBench"
:
Benchmark Mode Cnt Score Error Units
ZippedBench.withZip thrpt 20 4902.519 ± 41.733 ops/s
ZippedBench.withZipped thrpt 20 8736.251 ± 36.730 ops/s
যা দেখায় যে zipped
সংস্করণটি প্রায় 80% বেশি থ্রুপুট পায় যা সম্ভবত আপনার পরিমাপের মতো কমবেশি একই।
বরাদ্দ পরিমাপ
আপনি এর সাথে জেএমএইচটি বরাদ্দগুলি পরিমাপ করতে বলতে পারেন -prof gc
:
Benchmark Mode Cnt Score Error Units
ZippedBench.withZip thrpt 5 4894.197 ± 119.519 ops/s
ZippedBench.withZip:·gc.alloc.rate thrpt 5 4801.158 ± 117.157 MB/sec
ZippedBench.withZip:·gc.alloc.rate.norm thrpt 5 1080120.009 ± 0.001 B/op
ZippedBench.withZip:·gc.churn.PS_Eden_Space thrpt 5 4808.028 ± 87.804 MB/sec
ZippedBench.withZip:·gc.churn.PS_Eden_Space.norm thrpt 5 1081677.156 ± 12639.416 B/op
ZippedBench.withZip:·gc.churn.PS_Survivor_Space thrpt 5 2.129 ± 0.794 MB/sec
ZippedBench.withZip:·gc.churn.PS_Survivor_Space.norm thrpt 5 479.009 ± 179.575 B/op
ZippedBench.withZip:·gc.count thrpt 5 714.000 counts
ZippedBench.withZip:·gc.time thrpt 5 476.000 ms
ZippedBench.withZipped thrpt 5 11248.964 ± 43.728 ops/s
ZippedBench.withZipped:·gc.alloc.rate thrpt 5 3270.856 ± 12.729 MB/sec
ZippedBench.withZipped:·gc.alloc.rate.norm thrpt 5 320152.004 ± 0.001 B/op
ZippedBench.withZipped:·gc.churn.PS_Eden_Space thrpt 5 3277.158 ± 32.327 MB/sec
ZippedBench.withZipped:·gc.churn.PS_Eden_Space.norm thrpt 5 320769.044 ± 3216.092 B/op
ZippedBench.withZipped:·gc.churn.PS_Survivor_Space thrpt 5 0.360 ± 0.166 MB/sec
ZippedBench.withZipped:·gc.churn.PS_Survivor_Space.norm thrpt 5 35.245 ± 16.365 B/op
ZippedBench.withZipped:·gc.count thrpt 5 863.000 counts
ZippedBench.withZipped:·gc.time thrpt 5 447.000 ms
… gc.alloc.rate.norm
সম্ভবত সবচেয়ে আকর্ষণীয় অংশ যেখানে দেখায় যে zip
সংস্করণটি তিনগুণ বেশি বরাদ্দ করা হচ্ছে zipped
।
অত্যাবশ্যক বাস্তবায়ন
যদি আমি জানতাম যে এই পদ্ধতিটি অত্যন্ত কর্মক্ষমতা-সংবেদনশীল প্রসঙ্গে বলা হয়ে থাকে, আমি সম্ভবত এটি এটি প্রয়োগ করতাম:
def ES3(arr: Array[Double], arr1: Array[Double]): Array[Double] = {
val minSize = math.min(arr.length, arr1.length)
val newArr = new Array[Double](minSize)
var i = 0
while (i < minSize) {
newArr(i) = arr(i) + arr1(i)
i += 1
}
newArr
}
নোট যে অন্যান্য উত্তর এক অপ্টিমাইজ সংস্করণ, অসদৃশ এই ব্যবহারের while
একটি পরিবর্তে for
যেহেতু for
এখনও Scala সংগ্রহ অভিযানের মধ্যে desugar হবে। আমরা এই বাস্তবায়ন ( withWhile
), অন্য উত্তরের অনুকূলিত (তবে স্থানে নয়) বাস্তবায়ন ( withFor
) এবং দুটি মূল বাস্তবায়ন তুলনা করতে পারি :
Benchmark Mode Cnt Score Error Units
ZippedBench.withFor thrpt 20 118426.044 ± 2173.310 ops/s
ZippedBench.withWhile thrpt 20 119834.409 ± 527.589 ops/s
ZippedBench.withZip thrpt 20 4886.624 ± 75.567 ops/s
ZippedBench.withZipped thrpt 20 9961.668 ± 1104.937 ops/s
এটি আবশ্যক এবং কার্যকরী সংস্করণগুলির মধ্যে একটি সত্যই বিশাল পার্থক্য এবং এই সমস্ত পদ্ধতির স্বাক্ষরগুলি হুবহু একরকম এবং বাস্তবায়নের ক্ষেত্রে একই শব্দার্থতত্ত্ব রয়েছে। এটা তোলে, বিশ্বব্যাপী রাষ্ট্র ব্যবহার করছেন ইত্যাদি অনুজ্ঞাসূচক বাস্তবায়নের মত নয় যদিও zip
এবংzipped
সংস্করণ আরো ভালো পঠনযোগ্য, আমি ব্যক্তিগতভাবে কোন অর্থে যা অনুজ্ঞাসূচক সংস্করণ "Scala আত্মা 'বা মনোভাব বিরুদ্ধে আছে মনে করি না, এবং আমি দ্বিধা করবে না সেগুলি নিজেই ব্যবহার করার জন্য।
ট্যাবলেট সহ
আপডেট: আমি tabulate
অন্য উত্তরের মন্তব্যের ভিত্তিতে মানদণ্ডে একটি বাস্তবায়ন যুক্ত করেছি :
def ES4(arr: Array[Double], arr1: Array[Double]): Array[Double] = {
val minSize = math.min(arr.length, arr1.length)
Array.tabulate(minSize)(i => arr(i) + arr1(i))
}
এটি zip
সংস্করণগুলির চেয়ে অনেক দ্রুত , যদিও আবশ্যকগুলির তুলনায় এখনও অনেক ধীর:
Benchmark Mode Cnt Score Error Units
ZippedBench.withTabulate thrpt 20 32326.051 ± 535.677 ops/s
ZippedBench.withZip thrpt 20 4902.027 ± 47.931 ops/s
এটিই আমি প্রত্যাশা করছিলাম, যেহেতু কোনও ফাংশন কল করার মতো অন্তর্নিহিত ব্যয়বহুল কিছুই নেই এবং কারণ সূচকে অ্যারে উপাদানগুলি অ্যাক্সেস করা খুব সস্তা cheap