(* Content-type: application/mathematica *) (*** Wolfram Notebook File ***) (* http://www.wolfram.com/nb *) (* CreatedBy='Mathematica 6.0' *) (*CacheID: 234*) (* Internal cache information: NotebookFileLineBreakTest NotebookFileLineBreakTest NotebookDataPosition[ 145, 7] NotebookDataLength[ 31540, 870] NotebookOptionsPosition[ 28272, 759] NotebookOutlinePosition[ 28677, 777] CellTagsIndexPosition[ 28634, 774] WindowFrame->Normal ContainsDynamic->False*) (* Beginning of Notebook Content *) Notebook[{ Cell[CellGroupData[{ Cell["Performance tips", "Title", CellChangeTimes->{{3.3918893128898463`*^9, 3.3918893187482705`*^9}}], Cell["\<\ A modern portable or desktop PC runs at 2 GHz or more. That means that it can \ do of the order of a billion (some machine instructions take several clocks \ to complete, others can be executed partly in parallel, so it is hard to be \ precise) calculations per second! As a result, many Mathematica calculations \ may happen so fast that speed is not an issue. Here are a few tips for \ improving performance. As far as possible, they should be applied in order \ \[Dash] i.e. don't waste time on the later items until you have checked the \ earlier ones!\ \>", "Text", CellChangeTimes->{ 3.392017412229861*^9, {3.3920174467995696`*^9, 3.3920175125140624`*^9}, { 3.392017618326213*^9, 3.3920176463364897`*^9}}], Cell[CellGroupData[{ Cell["The 10% rule", "Section", CellChangeTimes->{{3.3920175605331106`*^9, 3.392017566521722*^9}}], Cell[TextData[{ "Unless you have already spent time optimising your code, it is virtually \ certain about 10% of the code is responsible for essentially all the delay \ you encounter in getting your results. This is true of all programming tasks \ \[Dash] whether using ", StyleBox["Mathematica", FontSlant->"Italic"], " or some other language such as C, Java, or Fortran. It is easy to waste \ time optimising some of the code from the 90% and see no improvement \ whatsoever! Therefore, the first task is to find the part of your code that \ is consuming the time. Assuming that your program can run on a range of data \ sets of various sizes, you should try to pick an example that takes \[Dash] \ say \[Dash] 30 seconds to run. You will end up running the code many times, \ so you don't want something that takes too long, but equally you need to be \ able to study that time delay." }], "Text", CellChangeTimes->{{3.392017586200018*^9, 3.3920176067996387`*^9}, { 3.392017654558312*^9, 3.3920180253314576`*^9}, {3.3920192312554913`*^9, 3.3920195042880926`*^9}, {3.392019535222574*^9, 3.392019595779651*^9}}], Cell[TextData[{ "The simplest way to identify the slow part of your code, is to add Print \ statements. This may sound crude, but if you can reach a point where two \ Print statements bracket a small chunk of code that takes a significant time \ to execute, that is real progress. Be ready for some surprises \[Dash] for \ example, some file formats can be Exported/Imported far more efficiently than \ others, and this often changes with new versions of ", StyleBox["Mathematica", FontSlant->"Italic"], "." }], "Text", CellChangeTimes->{{3.392017586200018*^9, 3.3920176067996387`*^9}, { 3.392017654558312*^9, 3.3920180253314576`*^9}, {3.3920192312554913`*^9, 3.3920195042880926`*^9}, {3.392019535222574*^9, 3.392019745134413*^9}, { 3.392019786954547*^9, 3.392019888370376*^9}}], Cell["\<\ I believe the Wolfram Workbench can also help to identify the hotspots in \ your code in a slightly more formal way called profiling. As yet, I have not \ explored this product \[Dash] I guess I am not a great fan of IDE's in any \ programming language, this may be a function of my age!\ \>", "Text", CellChangeTimes->{{3.392020073436488*^9, 3.392020257581275*^9}}] }, Open ]], Cell[CellGroupData[{ Cell["Avoid nasty surprises!", "Section", CellChangeTimes->{{3.3920175605331106`*^9, 3.392017566521722*^9}, { 3.3920204634372816`*^9, 3.392020489454693*^9}, {3.392022690820101*^9, 3.3920227125813923`*^9}}], Cell[TextData[{ "The speed of a Mathematica calculation can be rather hard to predict, so it \ is ", StyleBox["important to avoid the trap ", FontVariations->{"Underline"->True}], "of developing a complex algorithm with miniature development data sets, \ only to discover when it is too late that your calculation is far too slow \ when applied in earnest." }], "Text", CellChangeTimes->{ 3.392017412229861*^9, {3.39201991200436*^9, 3.3920199127454257`*^9}, 3.3920227514472785`*^9}] }, Open ]], Cell[CellGroupData[{ Cell["The curse of generality", "Section", CellChangeTimes->{{3.3920175605331106`*^9, 3.392017566521722*^9}, { 3.3920204634372816`*^9, 3.392020489454693*^9}, {3.392022690820101*^9, 3.3920227125813923`*^9}, {3.3920228467342944`*^9, 3.3920228548059006`*^9}}], Cell[TextData[{ StyleBox["Mathematica", FontSlant->"Italic"], " can manipulate a wide variety of objects, such as integers, reals, \ fractions, surds, and symbolic expressions. Sometimes this generality can \ create problems, and quite straightforward code can seem to execute \ unbelievably slowly. Consider the following loop, which applies three cycles \ of Newton's method for approximating a square root: " }], "Text", CellChangeTimes->{ 3.392017412229861*^9, {3.39201991200436*^9, 3.3920199127454257`*^9}, { 3.3920227514472785`*^9, 3.3920227549222755`*^9}, {3.3920228609246993`*^9, 3.3920230625045567`*^9}, {3.3920230975749855`*^9, 3.3920231233119936`*^9}}], Cell[BoxData[ RowBox[{ RowBox[{"mySqrt", "[", "A_", "]"}], ":=", RowBox[{"Module", "[", RowBox[{ RowBox[{"{", RowBox[{ RowBox[{"x", "=", "1"}], ",", RowBox[{"k", "=", "3"}]}], "}"}], ",", "\[IndentingNewLine]", RowBox[{ RowBox[{"While", "[", RowBox[{ RowBox[{"k", ">", "0"}], ",", "\[IndentingNewLine]", RowBox[{ RowBox[{"x", "=", RowBox[{ RowBox[{"x", "/", "2"}], "+", RowBox[{"A", "/", RowBox[{"(", RowBox[{"2", " ", "x"}], ")"}]}]}]}], ";", "\[IndentingNewLine]", RowBox[{"k", "--"}], ";"}]}], "\[IndentingNewLine]", "]"}], ";", "\[IndentingNewLine]", "x"}]}], "\[IndentingNewLine]", "]"}]}]], "Input",\ CellChangeTimes->{{3.3918894728098*^9, 3.391889534818965*^9}, { 3.391889581846587*^9, 3.391889582327278*^9}}], Cell["\<\ This definition works fine with real data, but look what happens if it \ applied to exact data:\ \>", "Text"], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{"mySqrt", "[", RowBox[{"Sqrt", "[", "7", "]"}], "]"}]], "Input", CellChangeTimes->{{3.3918895974390078`*^9, 3.391889621693885*^9}}], Cell[BoxData[ RowBox[{ FractionBox[ SqrtBox["7"], RowBox[{"2", " ", RowBox[{"(", RowBox[{ FractionBox[ SqrtBox["7"], RowBox[{"2", " ", RowBox[{"(", RowBox[{ FractionBox["1", "2"], "+", FractionBox[ SqrtBox["7"], "2"]}], ")"}]}]], "+", RowBox[{ FractionBox["1", "2"], " ", RowBox[{"(", RowBox[{ FractionBox["1", "2"], "+", FractionBox[ SqrtBox["7"], "2"]}], ")"}]}]}], ")"}]}]], "+", RowBox[{ FractionBox["1", "2"], " ", RowBox[{"(", RowBox[{ FractionBox[ SqrtBox["7"], RowBox[{"2", " ", RowBox[{"(", RowBox[{ FractionBox["1", "2"], "+", FractionBox[ SqrtBox["7"], "2"]}], ")"}]}]], "+", RowBox[{ FractionBox["1", "2"], " ", RowBox[{"(", RowBox[{ FractionBox["1", "2"], "+", FractionBox[ SqrtBox["7"], "2"]}], ")"}]}]}], ")"}]}]}]], "Output", CellChangeTimes->{{3.3918896049898653`*^9, 3.3918896224149218`*^9}}] }, Open ]], Cell["\<\ When you look at this expression it is hardly surprising that this is rather \ inefficient \[Dash] in effect, we have forced Mathematica to perform a huge \ algebraic calculation! Of course, this problem is easy to rectify once it is \ recognised, the insidious thing is that the expression might be generated and \ only subsequently reduced to a number. The only evidence that something \ unusual was happening would be the time required to obtain the result. Notice that in the above definition we used a loop count of 3. In a more \ realistic definition a larger loop count would be used, or the FixedPoint \ function might be used. In that case the calculation would probably just \ hang!\ \>", "Text", CellChangeTimes->{3.392023180374045*^9}] }, Open ]], Cell[CellGroupData[{ Cell["Functional programming", "Section", CellChangeTimes->{{3.3920175605331106`*^9, 3.392017566521722*^9}, { 3.3920204634372816`*^9, 3.392020489454693*^9}, {3.392022690820101*^9, 3.3920227125813923`*^9}, {3.3920228467342944`*^9, 3.3920228548059006`*^9}, { 3.3921454378421535`*^9, 3.3921454699082623`*^9}, {3.3921846231650944`*^9, 3.3921846340607615`*^9}}], Cell[TextData[{ "Open any ", StyleBox["Mathematica", FontSlant->"Italic"], " book and you are bound to read about the virtues of functional \ programming. There is indeed value in functional programming, but I want \ first to add a little perspective. Here is a trivial example of some \ functional programming \[Dash] applying the function Sin to a list of \ numbers:" }], "Text", CellChangeTimes->{ 3.392023180374045*^9, {3.3920478731505136`*^9, 3.3920478745925875`*^9}, { 3.39218464218244*^9, 3.392184779680152*^9}, {3.392184958066659*^9, 3.3921850386625504`*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{"Map", "[", RowBox[{"Sin", ",", RowBox[{"{", RowBox[{".1", ",", ".2", ",", ".3", ",", ".4", ",", ".5"}], "}"}]}], "]"}]], "Input", CellChangeTimes->{{3.392185042788483*^9, 3.3921850576198096`*^9}}], Cell[BoxData[ RowBox[{"{", RowBox[{ "0.09983341664682815`", ",", "0.19866933079506122`", ",", "0.29552020666133955`", ",", "0.3894183423086505`", ",", "0.479425538604203`"}], "}"}]], "Output", CellChangeTimes->{3.3921850587514367`*^9}] }, Open ]], Cell["or, using the fact that Sin has attribute Listable:", "Text", CellChangeTimes->{{3.392187427177066*^9, 3.3921874461643677`*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{ RowBox[{"{", RowBox[{".1", ",", ".2", ",", ".3", ",", ".4", ",", ".5"}], "}"}], "//", "Sin"}]], "Input", CellChangeTimes->{{3.392187452233094*^9, 3.392187471370613*^9}}], Cell[BoxData[ RowBox[{"{", RowBox[{ "0.09983341664682815`", ",", "0.19866933079506122`", ",", "0.29552020666133955`", ",", "0.3894183423086505`", ",", "0.479425538604203`"}], "}"}]], "Output", CellChangeTimes->{3.392187472442154*^9}] }, Open ]], Cell[TextData[{ "We are told that constructions like that are more efficient than a loop \ (based perhaps on While), and indeed, this is the case. However, it is \ instructive to think about exactly why this is so. At first glance, you might \ think that either of these constructs allow all the Sin calculations to get \ done in parallel, however, this is not true, even if you are using a \ multi-core CPU! Strangely enough, ultimately, ", StyleBox["Mathematica", FontSlant->"Italic"], " computes all those trig functions in a loop \[Dash] because it has to use \ the instructions available in your computer architecture. If you could \ translate that loop back into ", StyleBox["Mathematica", FontSlant->"Italic"], " code, it would look remarkably like the inefficient code that we are told \ not to use:" }], "Text", CellChangeTimes->{{3.392185084919064*^9, 3.3921854582158384`*^9}, { 3.392185498964432*^9, 3.3921855071862545`*^9}, {3.392185552200982*^9, 3.392185594371621*^9}, {3.392185630273245*^9, 3.39218571531553*^9}, { 3.3921857904035006`*^9, 3.3921857936281376`*^9}, {3.392187392997918*^9, 3.3921874195360785`*^9}, {3.392187499090472*^9, 3.392187532198078*^9}}], Cell[CellGroupData[{ Cell[BoxData[{ RowBox[{ RowBox[{"ans", "=", RowBox[{"{", RowBox[{".1", ",", ".2", ",", ".3", ",", ".4", ",", ".5"}], "}"}]}], ";"}], "\[IndentingNewLine]", RowBox[{ RowBox[{"k", "=", RowBox[{"Length", "[", "ans", "]"}]}], ";"}], "\[IndentingNewLine]", RowBox[{ RowBox[{"While", "[", RowBox[{ RowBox[{"k", ">", "0"}], ",", "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"ans", "[", RowBox[{"[", "k", "]"}], "]"}], "=", RowBox[{"Sin", "[", RowBox[{"ans", "[", RowBox[{"[", "k", "]"}], "]"}], "]"}]}], ";", "\[IndentingNewLine]", RowBox[{"k", "--"}], ";"}]}], "\[IndentingNewLine]", "]"}], ";"}], "\[IndentingNewLine]", "ans"}], "Input", CellChangeTimes->{{3.392185720032312*^9, 3.3921857807496195`*^9}}], Cell[BoxData[ RowBox[{"{", RowBox[{ "0.09983341664682815`", ",", "0.19866933079506122`", ",", "0.29552020666133955`", ",", "0.3894183423086505`", ",", "0.479425538604203`"}], "}"}]], "Output", CellChangeTimes->{3.392185782652355*^9}] }, Open ]], Cell["\<\ The loop might spin in the opposite direction, but the essence of the code \ would be as shown.\ \>", "Text", CellChangeTimes->{{3.392185829710021*^9, 3.3921858862613373`*^9}}], Cell[TextData[{ "In order to understand this paradox, it is necessary to understand that \ when ", StyleBox["Mathematica", FontSlant->"Italic"], " executes a loop such as the one above, it has to do far more work than \ simply performing the required calculations. There is a big overhead attached \ to each step. Consider just one line:" }], "Text", CellChangeTimes->{{3.3921858994603167`*^9, 3.392185923534934*^9}, { 3.3921859870162163`*^9, 3.3921860002953105`*^9}, {3.3921860309994607`*^9, 3.392186065859587*^9}, {3.392186100088806*^9, 3.392186146165061*^9}, { 3.392186602431139*^9, 3.3921866039833713`*^9}}], Cell[BoxData[ RowBox[{ RowBox[{"k", "--"}], ";"}]], "Input", CellChangeTimes->{{3.3921861514626784`*^9, 3.3921861539162064`*^9}}], Cell[TextData[{ "Executed as a machine instruction to increment the value of an integer, \ this might take 1-3 instructions, depending on the architecture. On a modern \ machine, that would take about 1 nanosecond. However, ", StyleBox["Mathematica", FontSlant->"Italic"], " must first determine if 'k' has a value (otherwise there is an error), and \ what sort of value it has \[Dash] it might be a real, or a rational, or even \ symbol. It also has to ensure that the built in 'Decrement' function has not \ been user modified. In addition, the concept of an integer is not quite the \ same to ", StyleBox["Mathematica", FontSlant->"Italic"], " as it is to the CPU. ", StyleBox["Mathematica", FontSlant->"Italic"], " integers never overflow (except for truly gigantic numbers that fill all \ of memory), and so ", StyleBox["Mathematica", FontSlant->"Italic"], " has to test for overflow and change the representation of the integer if \ necessary." }], "Text", CellChangeTimes->{{3.392186163289685*^9, 3.392186406649619*^9}, { 3.3921864469876223`*^9, 3.3921865659586945`*^9}, {3.3921866265758576`*^9, 3.392186627477154*^9}, {3.3921866943933744`*^9, 3.3921869640310946`*^9}, { 3.392187635386456*^9, 3.3921876379401283`*^9}}], Cell[TextData[{ "All of this work takes time and will happen on each turn of the loop. The \ point is that each individual step of a calculation carries an overhead like \ this, so if you can do a ", StyleBox["Mathematica", FontSlant->"Italic"], " calculation in a small number of large steps (such as the above Map \ function call) then you will get better performance. Functional programming \ offers little if any speed advantage in conventional compiled programming \ languages, because the variables have pre-declared types, and the programmer \ is responsible for avoiding overflow situations. " }], "Text", CellChangeTimes->{{3.392186163289685*^9, 3.392186406649619*^9}, { 3.3921864469876223`*^9, 3.3921865659586945`*^9}, {3.3921866265758576`*^9, 3.392186627477154*^9}, {3.3921866943933744`*^9, 3.392186738616965*^9}, { 3.392186968357315*^9, 3.3921872895491667`*^9}, {3.3921877143299713`*^9, 3.3921877156518717`*^9}}], Cell[TextData[{ "Put another way, in the context of ", StyleBox["Mathematica", FontSlant->"Italic"], ", functional programming is a good way to reduce the number of individual \ steps in a calculation and thereby reduce the associated overhead. Let us now \ examine how big this gain can be. To do this, we really need a longer vector \ if numbers:" }], "Text", CellChangeTimes->{{3.3921877315246964`*^9, 3.3921878274125757`*^9}, { 3.392187959152008*^9, 3.392188022513117*^9}}], Cell[BoxData[ RowBox[{ RowBox[{"vec", "=", RowBox[{"Table", "[", RowBox[{ RowBox[{"RandomReal", "[", RowBox[{"{", RowBox[{"0", ",", "5"}], "}"}], "]"}], ",", RowBox[{"{", SuperscriptBox["10", "7"], "}"}]}], "]"}]}], ";"}]], "Input", CellChangeTimes->{{3.3921880263786755`*^9, 3.392188109798627*^9}, { 3.392188158138136*^9, 3.3921881583284097`*^9}, 3.3921882201773443`*^9, { 3.39218833123704*^9, 3.392188332659085*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{ RowBox[{"(", RowBox[{ RowBox[{"Map", "[", RowBox[{"Sin", ",", "vec"}], "]"}], ";"}], ")"}], "//", "Timing"}]], "Input", CellChangeTimes->{{3.392188128775915*^9, 3.3921881467217197`*^9}}], Cell[BoxData[ RowBox[{"{", RowBox[{"3.2839999999999994`", ",", "Null"}], "}"}]], "Output", CellChangeTimes->{{3.3921881473426127`*^9, 3.3921881643570786`*^9}, 3.3921882290000305`*^9, 3.392188344736451*^9}] }, Open ]], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{ RowBox[{"(", RowBox[{ RowBox[{"Sin", "[", "vec", "]"}], ";"}], ")"}], "//", "Timing"}]], "Input",\ CellChangeTimes->{{3.392188188672042*^9, 3.3921882037937856`*^9}}], Cell[BoxData[ RowBox[{"{", RowBox[{"0.2709999999999992`", ",", "Null"}], "}"}]], "Output", CellChangeTimes->{{3.392188206107112*^9, 3.39218823175399*^9}, 3.3921883459982653`*^9}] }, Open ]], Cell[CellGroupData[{ Cell[BoxData[{ RowBox[{ RowBox[{"ans", "=", "vec"}], ";"}], "\[IndentingNewLine]", RowBox[{ RowBox[{"k", "=", RowBox[{"Length", "[", "ans", "]"}]}], ";"}], "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"While", "[", RowBox[{ RowBox[{"k", ">", "0"}], ",", "\[IndentingNewLine]", RowBox[{ RowBox[{ RowBox[{"ans", "[", RowBox[{"[", "k", "]"}], "]"}], "=", RowBox[{"Sin", "[", RowBox[{"ans", "[", RowBox[{"[", "k", "]"}], "]"}], "]"}]}], ";", "\[IndentingNewLine]", RowBox[{"k", "--"}], ";"}]}], "\[IndentingNewLine]", "]"}], ";"}], "//", "Timing"}]}], "Input", CellChangeTimes->{{3.3921885701706095`*^9, 3.3921885956071854`*^9}}], Cell[BoxData[ RowBox[{"{", RowBox[{"117.879`", ",", "Null"}], "}"}]], "Output", CellChangeTimes->{3.3921885865541677`*^9, 3.3921887170317855`*^9}] }, Open ]], Cell[TextData[{ "In the above calculations I have adjusted the expressions slightly to throw \ away the results ", Cell[BoxData[ FormBox[ RowBox[{"(", RowBox[{"you", " ", "did", " ", "not", " ", "want", " ", "to", " ", SuperscriptBox["read10", "7"]}]}], TraditionalForm]]], " numbers), and I also had to adjust the size of the array so as to get \ reasonable timing information." }], "Text", CellChangeTimes->{{3.3921882718516483`*^9, 3.392188420966064*^9}, { 3.392188491347267*^9, 3.392188526948459*^9}, {3.392188782255573*^9, 3.392188797858008*^9}}], Cell[TextData[{ "Notice first that using the Listable attribute of Sin is over 12 times more \ efficient than using Map! The main lesson to learn from this seems to be that \ ", StyleBox["Mathematica", FontSlant->"Italic"], " constructs can vary in performance quite remarkably, and it pays to do \ some experiments." }], "Text", CellChangeTimes->{{3.392211620120384*^9, 3.3922116490519857`*^9}, { 3.3922116860451794`*^9, 3.392211741474883*^9}, {3.392211784086155*^9, 3.392211786289323*^9}, {3.3922118177745967`*^9, 3.392211858763536*^9}}], Cell["\<\ The explicit loop is 35 times as expensive as even the Map construct \[Dash] \ and illustrates the benefit of avoiding explicit loops where possible. Note \ that Sin is a built-in function. If instead we used a complicated \ user-defined function in either construct, then the relative gain might be \ much less. Functional constructions can become very complicated in situations \ in which, perhaps, not all values of 'k' are to be treated the same way \ \[Dash] reasonable judgement is called for.\ \>", "Text", CellChangeTimes->{{3.392211903557947*^9, 3.3922120184531584`*^9}, { 3.3922161053498273`*^9, 3.3922162960139885`*^9}}] }, Open ]], Cell[CellGroupData[{ Cell["Packed arrays", "Section", CellChangeTimes->{{3.3920175605331106`*^9, 3.392017566521722*^9}, { 3.3920204634372816`*^9, 3.392020489454693*^9}, {3.392022690820101*^9, 3.3920227125813923`*^9}, {3.3920228467342944`*^9, 3.3920228548059006`*^9}, { 3.3921454378421535`*^9, 3.3921454699082623`*^9}, {3.3921846231650944`*^9, 3.3921846340607615`*^9}, {3.3922163204891825`*^9, 3.392216326778226*^9}}], Cell[TextData[{ "Let us re-run the first two experiments with one \[Dash] seemingly \ insignificant \[Dash] change. We rplace one of the ", Cell[BoxData[ FormBox[ RowBox[{ SuperscriptBox["10", "7"], " ", "array", " ", "elements", " ", "with", " ", "an", " ", RowBox[{"integer", ":"}]}], TraditionalForm]]] }], "Text", CellChangeTimes->{{3.392223465733539*^9, 3.392223553099165*^9}}], Cell[BoxData[ RowBox[{ RowBox[{"vec", "=", RowBox[{"Table", "[", RowBox[{ RowBox[{"RandomReal", "[", RowBox[{"{", RowBox[{"0", ",", "5"}], "}"}], "]"}], ",", RowBox[{"{", SuperscriptBox["10", "7"], "}"}]}], "]"}]}], ";"}]], "Input", CellChangeTimes->{{3.3921880263786755`*^9, 3.392188109798627*^9}, { 3.392188158138136*^9, 3.3921881583284097`*^9}, 3.3921882201773443`*^9, { 3.39218833123704*^9, 3.392188332659085*^9}}], Cell[BoxData[ RowBox[{ RowBox[{ RowBox[{"vec", "[", RowBox[{"[", "45", "]"}], "]"}], "=", "1"}], ";"}]], "Input", CellChangeTimes->{{3.392216393363971*^9, 3.392216404039322*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{ RowBox[{"(", RowBox[{ RowBox[{"Map", "[", RowBox[{"Sin", ",", "vec"}], "]"}], ";"}], ")"}], "//", "Timing"}]], "Input", CellChangeTimes->{{3.392188128775915*^9, 3.3921881467217197`*^9}}], Cell[BoxData[ RowBox[{"{", RowBox[{"10.64499999999999`", ",", "Null"}], "}"}]], "Output", CellChangeTimes->{{3.3921881473426127`*^9, 3.3921881643570786`*^9}, 3.3921882290000305`*^9, 3.392188344736451*^9, 3.3922163868946686`*^9, 3.3922165533740544`*^9}] }, Open ]], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{ RowBox[{"(", RowBox[{ RowBox[{"Sin", "[", "vec", "]"}], ";"}], ")"}], "//", "Timing"}]], "Input",\ CellChangeTimes->{{3.392188188672042*^9, 3.3921882037937856`*^9}}], Cell[BoxData[ RowBox[{"{", RowBox[{"11.86700000000001`", ",", "Null"}], "}"}]], "Output", CellChangeTimes->{{3.392188206107112*^9, 3.39218823175399*^9}, 3.3921883459982653`*^9, 3.392216388256627*^9, 3.3922166531775646`*^9}] }, Open ]], Cell[TextData[{ "These timings are substantially greater than before, and do not seem to \ reflect the actual elapsed time. This is almost certainly due to the fact \ that substantial page-swapping is going on. This is a dramatic illustration \ of yet another feature of ", StyleBox["Mathematica", FontSlant->"Italic"], " programming." }], "Text", CellChangeTimes->{{3.392223570604336*^9, 3.3922236892349186`*^9}}], Cell[TextData[{ "In early versions of ", StyleBox["Mathematica", FontSlant->"Italic"], ", a List was simply a ", StyleBox["Mathematica", FontSlant->"Italic"], " data structure like any other, with 'List' as its head. For many examples \ of lists, this is still true, but homogenous arrays (in one or more \ dimensions) of reals, integers, and complex numbers can also be stored as \ packed arrays, which resemble arrays in Fortran or C. Such arrays are much \ more compact, and can also be accessed at very high speed. The system can \ choose to convert between its two representations of lists in a totally \ silent way, because the results of no ordinary calculations depend on this \ representation \[Dash] only the efficiency varies. Note in particular, that \ just because a particular list is elligible to be packed, does not \ necessarily mean that it will be. Some functions, such as 'Table', seem to \ pack their result where possible, but it is easy to create an array that is \ unpacked but could be packed." }], "Text", CellChangeTimes->{{3.3922242112555475`*^9, 3.392224290960157*^9}, { 3.392226845984101*^9, 3.392227149370349*^9}, {3.392275915700779*^9, 3.392276049312904*^9}, {3.392276079486291*^9, 3.392276105073083*^9}}], Cell["\<\ The large vector in the previous example was unpacked when the following \ statement turned it into a mixture of reals and integers.\ \>", "Text", CellChangeTimes->{{3.3922761271648493`*^9, 3.3922761901554255`*^9}}], Cell[BoxData[ RowBox[{ RowBox[{ RowBox[{"vec", "[", RowBox[{"[", "45", "]"}], "]"}], "=", "1"}], ";"}]], "Input", CellChangeTimes->{{3.392216393363971*^9, 3.392216404039322*^9}}], Cell["The following statement could be used to fix that:", "Text", CellChangeTimes->{{3.3922762014216256`*^9, 3.3922762248052497`*^9}, { 3.3922763234571037`*^9, 3.392276329315528*^9}}], Cell[BoxData[ RowBox[{ RowBox[{"vec", "=", RowBox[{"Developer`ToPackedArray", "[", RowBox[{"N", "[", "vec", "]"}], "]"}]}], ";"}]], "Input", CellChangeTimes->{{3.3922762305334864`*^9, 3.39227623147484*^9}, { 3.3922762805453997`*^9, 3.3922762894682302`*^9}, {3.3922763384987326`*^9, 3.3922763492642126`*^9}, {3.3922764021602736`*^9, 3.3922764084593315`*^9}}],\ Cell["\<\ This uses 'N' to make the array homogenous once more, followed by \ Developer`ToPackedArray, which packs its argument if possible. It is also \ possible to test an array to determine if it is indeed packed:\ \>", "Text", CellChangeTimes->{{3.392276485309837*^9, 3.3922766093582096`*^9}}], Cell[CellGroupData[{ Cell[BoxData[ RowBox[{"vec", "//", "Developer`PackedArrayQ"}]], "Input", CellChangeTimes->{{3.392276300023408*^9, 3.392276310218067*^9}}], Cell[BoxData["True"], "Output", CellChangeTimes->{3.3922763111694355`*^9, 3.392276358106928*^9, 3.3922764168013268`*^9, 3.392276475926344*^9}] }, Open ]], Cell[TextData[{ "Even though these functions are in Developer` context, they are vital for \ anyone who wants to optimise ", StyleBox["Mathematica", FontSlant->"Italic"], " code involving large arrays." }], "Text", CellChangeTimes->{{3.392276613704459*^9, 3.3922767118355646`*^9}}] }, Open ]], Cell[CellGroupData[{ Cell["Conclusion", "Section", CellChangeTimes->{{3.3920175605331106`*^9, 3.392017566521722*^9}, { 3.3920204634372816`*^9, 3.392020489454693*^9}, {3.392022690820101*^9, 3.3920227125813923`*^9}, {3.3920228467342944`*^9, 3.3920228548059006`*^9}, { 3.3921454378421535`*^9, 3.3921454699082623`*^9}, {3.3921846231650944`*^9, 3.3921846340607615`*^9}, {3.3922163204891825`*^9, 3.392216326778226*^9}, { 3.3922237016127167`*^9, 3.3922237081421056`*^9}}], Cell[TextData[{ "The above is really just an introduction to the complex matter of \ optimising ", StyleBox["Mathematica", FontSlant->"Italic"], " code. If you feel your ", StyleBox["Mathematica", FontSlant->"Italic"], " code needs speeding up, I may be able to help. I will look at your code \ and attempt to improve its performance. Only if I succeed, will I request a \ consultancy fee in return for the enhanced code." }], "Text", CellChangeTimes->{{3.392223718496995*^9, 3.3922239621573615`*^9}}], Cell["\<\ Obviously, I may decide that I do not wish to work with particular pieces of \ code for any of a variety of reasons, but in that case you will only have \ wasted the electricity required to send me an e-mail!\ \>", "Text", CellChangeTimes->{{3.3922239718713293`*^9, 3.3922240807478867`*^9}, { 3.3922757550597887`*^9, 3.392275874591667*^9}}] }, Open ]] }, Open ]] }, WindowSize->{1037, 750}, WindowMargins->{{Automatic, 108}, {Automatic, 65}}, ShowSelection->True, ShowCellLabel->False, Magnification->1, FrontEndVersion->"6.0 for Microsoft Windows (32-bit) (March 26, 2007)", StyleDefinitions->"Default.nb" ] (* End of Notebook Content *) (* Internal cache information *) (*CellTagsOutline CellTagsIndex->{} *) (*CellTagsIndex CellTagsIndex->{} *) (*NotebookFileOutline Notebook[{ Cell[CellGroupData[{ Cell[590, 23, 103, 1, 123, "Title"], Cell[696, 26, 727, 12, 139, "Text"], Cell[CellGroupData[{ Cell[1448, 42, 99, 1, 105, "Section"], Cell[1550, 45, 1123, 18, 188, "Text"], Cell[2676, 65, 791, 14, 115, "Text"], Cell[3470, 81, 377, 6, 90, "Text"] }, Open ]], Cell[CellGroupData[{ Cell[3884, 92, 211, 3, 105, "Section"], Cell[4098, 97, 494, 11, 90, "Text"] }, Open ]], Cell[CellGroupData[{ Cell[4629, 113, 262, 3, 105, "Section"], Cell[4894, 118, 677, 12, 90, "Text"], Cell[5574, 132, 873, 25, 201, "Input"], Cell[6450, 159, 119, 3, 41, "Text"], Cell[CellGroupData[{ Cell[6594, 166, 158, 3, 39, "Input"], Cell[6755, 171, 1096, 41, 122, "Output"] }, Open ]], Cell[7866, 215, 759, 13, 188, "Text"] }, Open ]], Cell[CellGroupData[{ Cell[8662, 233, 367, 5, 105, "Section"], Cell[9032, 240, 582, 13, 90, "Text"], Cell[CellGroupData[{ Cell[9639, 257, 236, 6, 39, "Input"], Cell[9878, 265, 250, 6, 38, "Output"] }, Open ]], Cell[10143, 274, 135, 1, 41, "Text"], Cell[CellGroupData[{ Cell[10303, 279, 203, 5, 39, "Input"], Cell[10509, 286, 248, 6, 38, "Output"] }, Open ]], Cell[10772, 295, 1193, 21, 164, "Text"], Cell[CellGroupData[{ Cell[11990, 320, 796, 22, 201, "Input"], Cell[12789, 344, 248, 6, 38, "Output"] }, Open ]], Cell[13052, 353, 187, 4, 41, "Text"], Cell[13242, 359, 624, 12, 90, "Text"], Cell[13869, 373, 133, 3, 39, "Input"], Cell[14005, 378, 1250, 26, 188, "Text"], Cell[15258, 406, 940, 16, 139, "Text"], Cell[16201, 424, 485, 10, 90, "Text"], Cell[16689, 436, 470, 12, 42, "Input"], Cell[CellGroupData[{ Cell[17184, 452, 230, 7, 39, "Input"], Cell[17417, 461, 214, 4, 38, "Output"] }, Open ]], Cell[CellGroupData[{ Cell[17668, 470, 201, 6, 39, "Input"], Cell[17872, 478, 187, 4, 38, "Output"] }, Open ]], Cell[CellGroupData[{ Cell[18096, 487, 730, 21, 174, "Input"], Cell[18829, 510, 151, 3, 38, "Output"] }, Open ]], Cell[18995, 516, 576, 13, 70, "Text"], Cell[19574, 531, 550, 11, 90, "Text"], Cell[20127, 544, 644, 10, 115, "Text"] }, Open ]], Cell[CellGroupData[{ Cell[20808, 559, 406, 5, 105, "Section"], Cell[21217, 566, 404, 10, 62, "Text"], Cell[21624, 578, 470, 12, 42, "Input"], Cell[22097, 592, 190, 5, 39, "Input"], Cell[CellGroupData[{ Cell[22312, 601, 230, 7, 39, "Input"], Cell[22545, 610, 265, 5, 38, "Output"] }, Open ]], Cell[CellGroupData[{ Cell[22847, 620, 201, 6, 39, "Input"], Cell[23051, 628, 232, 4, 27, "Output"] }, Open ]], Cell[23298, 635, 420, 9, 47, "Text"], Cell[23721, 646, 1252, 22, 101, "Text"], Cell[24976, 670, 226, 4, 29, "Text"], Cell[25205, 676, 190, 5, 28, "Input"], Cell[25398, 683, 187, 2, 29, "Text"], Cell[25588, 687, 375, 7, 28, "Input"], Cell[25968, 697, 298, 5, 47, "Text"], Cell[CellGroupData[{ Cell[26291, 706, 139, 2, 28, "Input"], Cell[26433, 710, 146, 2, 27, "Output"] }, Open ]], Cell[26594, 715, 287, 7, 29, "Text"] }, Open ]], Cell[CellGroupData[{ Cell[26918, 727, 456, 6, 71, "Section"], Cell[27377, 735, 511, 12, 47, "Text"], Cell[27891, 749, 353, 6, 47, "Text"] }, Open ]] }, Open ]] } ] *) (* End of internal cache information *)