{"id":4460,"date":"2014-03-30T11:14:44","date_gmt":"2014-03-30T11:14:44","guid":{"rendered":"https:\/\/unknownerror.org\/index.php\/2014\/03\/30\/in-ocaml-how-big-is-the-price-of-abstraction-i-e-polymorphic-functions-collection-of-common-programming-errors\/"},"modified":"2014-03-30T11:14:44","modified_gmt":"2014-03-30T11:14:44","slug":"in-ocaml-how-big-is-the-price-of-abstraction-i-e-polymorphic-functions-collection-of-common-programming-errors","status":"publish","type":"post","link":"https:\/\/unknownerror.org\/index.php\/2014\/03\/30\/in-ocaml-how-big-is-the-price-of-abstraction-i-e-polymorphic-functions-collection-of-common-programming-errors\/","title":{"rendered":"In OCaml, how big is the price of abstraction (i.e. polymorphic functions)-Collection of common programming errors"},"content":{"rendered":"<p>I&#8217;m still in the early phase of learning OCaml and am curious to know what the best way to extract maximum performance out of generic code in OCaml is.<\/p>\n<p>As a small experiment, I&#8217;ve written two polymorphic functions: one in C++ and the other in OCaml that find the largest element in a given array.<\/p>\n<p>What I&#8217;ve observed is that while in C++ you pay no penalty for this sort of abstraction, the penalty in OCaml is a whopping one degree of magnitude drop in performance. And as an aside, the C++ solution I quickly concocted is more generic that the OCaml one, but I blame that primarily on my inexperience with the language.<\/p>\n<p>My question is the following: how to write and use polymorphic functions in OCaml without paying the huge performance penalty that I&#8217;ve just observed?<\/p>\n<p>Another thing I observed for this particular problem is that my functional solution in OCaml was slower than the imperative one, whereas the &#8220;functional&#8221; solution in C++ suffered no penalties compared to the analogue imperative approach.<\/p>\n<p>C++ code was compiled with <code>g++ -std=\"c++0x\" -O3 -o max_cpp max.cpp<\/code>, using gcc-4.6.3 and OCaml code with: <code>ocamlopt -o max_ml max.ml<\/code> using ocamlopt version 3.12.1. Both of the generated executables were 32 bit and run on Ubuntu x64 11.04<\/p>\n<p>I submit the code of both programs.<\/p>\n<p>C++ code (not entirely safe, of course \ud83d\ude09 )<\/p>\n<pre><code>#include \n#include \n#include \ntemplate  T max (T a, T b) {\n     return (a&gt;b)? a : b;\n}\n\ntemplate  typename I::value_type find_max (I begin, I end) {\n    auto max = *begin;\n    for (begin++;begin!=end;begin++)\n            if (*begin &gt; max) max = *begin;\n    return max;\n}\n\ntemplate  typename I::value_type find_max1(I begin, I end) {\n    return std::accumulate(begin, end, *begin, max&lt; typename I::value_type&gt; );\n}\n\nint main(int argc, char ** argv) {\n    const size_t nElem = atoi(argv[1]);\n    const size_t nIter = atoi(argv[2]);\n    std::vector intA(nElem);\n    std::vector dubA(nElem);\n    for (int i=0;i<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;m still in the early phase of learning OCaml and am curious to know what the best way to extract maximum performance out of generic code in OCaml is. As a small experiment, I&#8217;ve written two polymorphic functions: one in C++ and the other in OCaml that find the largest element in a given array. [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-4460","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/4460","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/comments?post=4460"}],"version-history":[{"count":0,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/4460\/revisions"}],"wp:attachment":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/media?parent=4460"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/categories?post=4460"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/tags?post=4460"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}