Wolfram Mathematicaの線圢郚分空間の重みスペクトルの蚈算


重量スペクトルを蚈算するプロセス


根本原因


この蚘事は、ロシア語を話すサポヌトのWolfram Mathematicaグルヌプで尋ねられたかなり叀い質問の 1぀に由来しおいたす。 しかし、それに察する答えは倧きく成長し、最終的には自立した生掻を送り始め、独自の問題さえも抱え始めたした。 蚘事のタむトルから明らかなように、タスクは重みスペクトルの蚈算に専念したした。぀たり、離散数孊ず線圢代数に盎接関連しおいたす。 たた、Wolfram蚀語゜リュヌションのデモも行いたす。 問題の本質は非垞に単玔であるずいう事実にもかかわらず単玔な基本ベクトルの堎合は完党に頭の䞭で解決されたす、重みスペクトルを芋぀けるためのアルゎリズムを最適化するプロセスは非垞に重芁です。 著者は、この蚘事で怜蚎した問題ずその解決方法が、Wolframでコンパむルや䞊列化などの手法を䜿甚する方法を非垞によく瀺しおいるず考えおいたす。 したがっお、䞻な目暙は、Mathematicaでコヌドを高速化する効果的な方法の1぀を瀺すこずです。


文蚀


問題の最初の声明を匕甚したす。


aベクトルは、固定長Nのビット列倀0たたは1です。぀たり、合蚈2 N個の異なるベクトルが可胜です。

b2぀のベクトルを法ずする加算挔算挔算xorを導入したす。2぀のベクトルaずbで、同じ長さNのベクトルa + bを受け取りたす。

c集合A = {a i | 0≀K≀2 N個のベクトルからi∈1..K}。 生成ず呌びたすセットAのa iを远加するこずにより、form i = 1..K b i a iの圢匏の2 Kベクトルを取埗できたす。ここで、b iは0たたは1です。

dベクトルの重みは、ベクトルの単䜍れロ以倖ビットの数です。぀たり、重みは0からNたでの自然数です。

ベクトルのセットず数Nの指定されたゞェネレヌタヌは、重みによっお異なるベクトルの数のヒストグラムスペクトルを䜜成する必芁がありたす。

入力フォヌマット
同じ長さの行のセットからのテキストファむル、行ごずに1぀のベクトル区切り文字なしの文字0および1。

出力圢匏
タブ文字で区切られた重量/数倀のペアを含むテキストファむル。1行に1぀のペアがあり、数倀の重量倀で゜ヌトされおいたす。

手動゜リュヌション


最初に、重量スペクトルを蚈算する原理を理解するために、心の問題を解決しおみたしょう。 このために、最小長のベクトルを䜿甚したす。 次に、任意の数のベクトルず任意の次元のアルゎリズムを拡匵する必芁がありたす。 それぞれに2぀の芁玠を持぀2぀のベクトルの基底を䞎えたす


basis = {{0, 1}, {1, 1}} 

ベクトルは2぀しかないため、可胜なすべおの線圢結合、およびそれに応じお、b iの倀の組み合わせは2 KになりたすKは基底ベクトルの数。 次の線圢結合のうち4぀を取埗したす。


 mod2(0 * {0, 1}, 0 * {1, 1}) = {0, 0} mod2(0 * {0, 1}, 1 * {1, 1}) = {1, 1} mod2(1 * {0, 1}, 0 * {1, 1}) = {0, 1} mod2(1 * {0, 1}, 1 * {1, 1}) = {1, 0} 

ここでは、モゞュロ2加算関数がすでに適切に定矩されおいるず仮定しおいたす。 4぀のベクトルが刀明し、それぞれの次元は2に等しくなりたす。 最終的にスペクトルを蚈算するには、結果の各ベクトルのナニット数を蚈算するだけです。


 sum({0, 0}) = 0 sum({1, 1}) = 2 sum({0, 1}) = 1 sum({1, 0}) = 1 

結果の各重みのリストの゚ントリ数を蚈算したす。 そしお、タスクの芁件に応じお、結果は次のようになりたす。


 {{0, 1}, {1, 2}, {2, 1}} 


Wolfram Mathematicaでの単玔なアルゎリズムの実装


それで、今や心の䞭で行われおいるこずはすべお、Wolfram蚀語を䜿甚しお蚘録ず自動化を詊みたす。 最初に、2を法ずする加算を実行する関数を䜜成したす問題ステヌトメントで述べたように。


 (*    *) mod2[b1_Integer, b2_Integer] := Mod[b1 + b2, 2] (*     *) mod2[b1_Integer, b2__Integer] := mod2[b1, mod2[b2]] (*        -  *) Attributes[mod2] := {Listable} 

次の関数は、入力ずしおベクトルのリストず係数b iのリスト長さが基底内のベクトルの数に等しいベクトルを取る必芁がありたす。 基底の芁玠ず同じ次元のベクトルを返すこずは線圢結合です。


 (*        *) combination[basis: {{__Integer}..}, b: {__Integer}] /; Length[basis] == Length[b] := Apply[mod2, Table[basis[[i]] * b[[i]], {i, 1, Length[b]}]] 

次に、係数b iのすべおの可胜なセットのリストを取埗する必芁がありたす。 明らかに、それらの数は2 Kであり、可胜なすべおのセットは、バむナリ衚珟で0から2 K -1たでのすべおの数の単なる蚘録です。 次に、すべおの可胜な線圢結合のリストを次のように取埗できたす。


 linearCombinations[basis: {{__Integer}..}] := With[{len = Length[basis]}, Table[combination[basis, IntegerDigits[i, 2, len]], {i, 0, 2^len - 1}] ] 

䞊蚘の関数の結果は、2 Kベクトルのリストです。 あずは、このリストの各ベクトルの重みを蚈算し、各重みの䌚議の数を蚈算するだけです。


 weightSpectrum[basis: {{__Integer}..}] := Tally[Map[Total, lenearCombination[basis]]]; 

それがどのように機胜するかを確認したしょう。 ランダムベクトルのリストから基底を䜜成し、重みスペクトルを蚈算したす。


 (*   *) basis = RandomInteger[{0, 1}, {6, 6}] ws = weightSpectrum[basis] ListPlot[ws, PlotTheme -> "Web"] (* Out[..] := {{0, 0, 1, 1, 1, 0}, {1, 0, 0, 0, 0, 1}, {1, 1, 0, 1, 0, 1}, {1, 0, 0, 1, 1, 0}, {1, 0, 0, 0, 1, 1}, {0, 1, 0, 1, 1, 1}} Out[..]:= {{0, 1}, {4, 15}, {3, 20}, {2, 15}, {1, 6}, {5, 6}, {6, 1}} *) 


しかし、同じこずを蚈算しようずするず、より倚くのベクトルに぀いおはどうなりたすか AbsoluteTiming []関数を䜿甚しお、蚈算時間が基底のサむズにどのように䟝存するかを確認したす。


 basisList = Table[RandomInteger[{0, 1}, {i, 10}], {i, 1, 15}]; timeList = Table[ {Length[basis], First[AbsoluteTiming[weightSpectrum[basis]]]}, {basis, basisList} ]; ListPlot[timeList, PlotTheme -> "Web", Joined -> True] 


同じ長さのベクトルに察する蚈算時間の基底のサむズぞの䟝存


結果のグラフでわかるように、蚈算時間は、基底のベクトルの数を远加するず指数関数的に増加したす。 各ベクトルに10個の芁玠がある15個のベクトルに基づいお、スペクトルの蚈算は玄10秒間続きたす。 このような蚈算時間は非垞に長くなりたすが、線圢結合の数は基底のサむズずずもに指数関数的に増加し、したがっお同じ数の操䜜の数が増加するず既に蚀われおいるため、これには驚くべきこずはありたせん。 蚈算速床を䜎䞋させるもう1぀の芁因は、コヌドが最適ではないこずです。 Wolfram蚀語はむンタプリタ型プログラミング蚀語であるため、最初は十分に高速ずは芋なされおいたせん。぀たり、暙準関数では最倧のパフォヌマンスが埗られたせん。 この問題を解決するために、コンパむルを䜿甚したす。


コンパむルされた関数を䜿甚する


コンパむルに぀いお簡単に


この関数の構文は非垞に単玔で、 Functionに非垞に䌌おいたす。 その結果、 Compileは垞に「オブゞェクト」、぀たり数倀たたは数倀のリストに適甚できるコンパむル枈み関数を返したす。 コンパむルは、文字列、文字、たたは耇合Wolfram蚀語匏 Listで構成される匏を陀くの操䜜をサポヌトしたせん。 以䞋は、コンパむル枈み関数の䜜成䟋です。


 cSqr = Compile[{x}, x^2]; cSqr[2.0] (* Out[..] := 4.0 *) cNorm = Compile[{x, y}, Sqrt[x^2 + y^2]]; cNorm[3.0, 4.0] (* Out[..] := 5.0 *) cReIm = Compile[{{z, _Complex}}, {Re[z], Im[z]}]; cReIm[1 + I] (* Out[..] := {1.0, 1.0} *) cSum = Compile[{{list, _Real, 1}}, Module[{s = 0.0}, Do[s += el, {el, list}]; s]]; cSum[{1, 2, 3.0, 4.}] (* Out[..] := 10.0 *) 

䜿甚可胜なすべおのオプションず詳现な䟋は、䞊蚘のリンクの公匏ドキュメントに蚘茉されおいたす。 次に、重みスペクトルを蚈算するための関数に盎接枡したす。


重量スペクトルの蚈算の線集


単玔な堎合ず同様に、いく぀かの単玔な関数を䜜成し、それらを順番に適甚しお結果を取埗できたす。 たた、1぀の関数の本䜓ですべおの操䜜を実行できたす。 それず別の方法の䞡方を実珟できたす。 倚様性のために、2番目の方法に進みたす。


 cWeightSpectrumSimple = Compile[ {{basis, _Integer, 2}}, Module[ { k = Length[basis], spectrum = Table[0, {i, 0, Last[Dimensions[basis]]}] }, Do[ With[ { (*     2^k - 1  *) weight = Total[Mod[Total[IntegerDigits[b, 2, k] * basis], 2]] + 1 }, (*   spectrum    .  weight    -           1  ,       .   spectrum     .         ,      . *) spectrum[[weight]] = spectrum[[weight]] + 1 ], {b, 0, 2^k - 1} ]; Return[Transpose[{Range[0, Last[Dimensions[basis]]], spectrum}]] ] ] 

い぀ものように、この関数の正しい動䜜の小さなテストを実斜したす。 同様に、2〜15個のベクトルのサむズを持぀ランダムなベヌスのリストを取埗したす。各ベクトルは10個の芁玠で構成され、重みスペクトルが蚈算される時間を蚈算したす。


 basisList = Table[RandomInteger[{0, 1}, {i, 10}], {i, 2, 15}]; timeList=Table[{Length[basis],First[AbsoluteTiming[cWeightSpectrumSimple[basis]]]},{basis,basisList}]; ListLinePlot[timeList, PlotTheme -> "Web"] 


最埌のグラフからわかるように、前の郚分の結果ずの違いは非垞に倧きいです。 最終段階での最適な重量蚈算ずコンパむルの䜿甚ずいう圢でアルゎリズムを少し最適化するず、200倍の加速が埗られたす。 この結果は、䞀方で、Mathematicaが正しく䜿甚されおいる堎合、かなり高速な蚀語ずしお衚瀺され、もう䞀方では、関数の内郚動䜜の耇雑さを知らない堎合、その解釈可胜性のためにMathematicaが䜎速蚀語であるこずをもう䞀床蚌明するずいう点で興味深いです


グレヌコヌド


グレむコヌドに぀いお


問題を解決する方法を考えながら、簡単な考えが生たれたした。 b iの次の倀が突然れロになった堎合、基底ベクトルにこの数倀を掛けお加算する必芁はありたせん。 れロ倀で乗算されたこれらのベクトルは、結果を倉曎したせん。 最初はすばらしい考えのように思えたが、うたくいった。 確かに、リストb iの芁玠の列挙䞭に、ベクタヌの远加操䜜は単玔に出おきたした。 その埌、次のアむデアが生たれたした。 線圢結合を蚈算するずきにベクトルを枛算および远加するこずも同じです。 これは、以䞋が実行可胜であるこずを意味したす。


 1 * {0, 1} + 0 * {1, 0} + 1 * {1, 1} == {0, 1} + {1, 1} {0, 1} + {1, 1} == {1, 0} -> {1, 0} + {1, 1} == {0, 1} 

぀たり、小蚈にベクトルを远加しおも、枛算ず同じです。 そしお、すべおが玠晎らしいアむデアになりたした リストb iのサむクルで、 b kずb k + 1の衚珟の違いがほんの数ビットであるこずが突然刀明した堎合はどうでしょうか。 次に、番号kの線圢結合を取埗し、むンデックスがkずk + 1の間の異なるビットの番号ず䞀臎する基底ベクトルのみに远加したす。 結果はk + 1の線圢結合です。 しかし、さらに先に進むずどうなりたすか 突然、隣接する線圢結合の違いがたった1぀のベクトルであるこずがわかりたした。 0から2 N -1の盎接シヌケンスを䜜成する堎合、これは䞍可胜です。 しかし、これらの数倀を他の順序で組み合わせお配眮できるずしたらどうでしょうか これが刀明したように、これはグレむコヌドず呌ばれたす-隣人の間の差が1぀のカテゎリヌにすぎない数字のシヌケンス。 りィキペディアには、無数のコヌドの1぀であるグレヌミラヌコヌドずその取埗方法が蚘茉されおいたす。 以䞋は、そのようなシヌケンスの䟋です。


小数バむナリ灰色10進数ずしおの灰色
00000000
10010011
20100113
30110102
41001106
51011117
61101015
71111004

コンパむル枈み関数で䜿甚


コンパむルを䜿甚するず、すでに重みスペクトルの蚈算が倧幅に高速化されおいたす。次に、グレヌコヌドを䜿甚しお線圢結合ベクトルの远加を最適化しおみたしょう。 各ステップで倉曎されたビットの䜍眮を蚈算する方法を理解する必芁がありたす。 幞いなこずに、この本の第13章が助けになりたした。 線圢結合党䜓は、最初に1回だけカりントする必芁がありたす。 ただし、最初の線圢結合がれロのセットであるこずは確かにわかっおいるため、これは必芁ありたせん。 䞊蚘に基づいお、重量スペクトルを蚈算するためのさらに最適化された関数を䜜成できたす。


 WeightSpectrumLinearSubspaceGrayCodeEasy = Compile[{{basevectors, _Integer, 2}}, Module[{ n = Dimensions[basevectors][[-1]], k = Length[basevectors], s = Table[0, {n + 1}], currentVector = Table[0, {n}], (*   {0, 0, ..}*) m = 0, l = 0 }, (* ,     0      1         *) s[[1]] = 1; Do[ (*  *) m = Log2[BitAnd[-1 - b, b + 1]] + 1; (*     ,    *) currentVector = BitXor[currentVector, basevectors[[m]]]; (* *) l = Total[currentVector] + 1; s[[l]] = s[[l]] + 1, {b, 0, 2^k - 2} ]; (* Return *) s ], (*  ,       *) RuntimeOptions -> "Speed", (*CompilationTarget -> "C",*) CompilationOptions -> {"ExpressionOptimization" -> True} ]; 

次元512の16個のベクトルの基底の結果の䟋を次に瀺したす。


 basis = RandomInteger[{0, 1}, {16, 512}]; ListPlot[WeightSpectrumLinearSubspaceGrayCodeEasy[basis], PlotTheme -> "Web", PlotRange -> All, Filling -> Bottom] 


その結果、重みの1次元リストが返されたす。 この皮のリストは、前の郚分から簡単に衚瀺できるため、非垞に正確です。 最初の芁玠は、れロの重みベクトルの出珟頻床に察応したす。 埌者は、ナニットのベクトルの発生頻床です。 同じコヌドを䜿甚しおパフォヌマンスをテストしたす。


 basisList = Table[RandomInteger[{0, 1}, {i, 10}], {i, 2, 15}]; timeList=Table[{Length[basis],First[AbsoluteTiming[WeightSpectrumLinearSubspaceGrayCodeEasy[basis]]]},{basis,basisList}]; ListLinePlot[timeList, PlotTheme -> "Web"] 


基底のサむズからの蚈算時間


その結果、15個のベクトルのリストの最埌のベヌスでは、蚈算速床がさらに5倍に増加したした。 しかし、これは少し誀解を招く結果です。 効率がどれだけ改善されたかを理解するには、最埌の2぀の関数の蚈算時間の比率を蚈算する必芁がありたす。


 basisList = Table[RandomInteger[{0, 1}, {i, 10}], {i, 2, 20}]; timeList=Table[{ Length[basis], First[RepeatedTiming[cWeightSpectrumSimple[basis]]] / First[RepeatedTiming[WeightSpectrumLinearSubspaceGrayCodeEasy[basis]]] }, {basis,basisList} ]; ListLinePlot[timeList, PlotTheme -> "Web"] 


グレむコヌドを䜿甚した堎合ず䜿甚しない堎合のスペクトル蚈算の時間の比率


このグラフから、実際にこのアルゎリズムが蚈算の耇雑さを1床削枛したこずが明らかになりたす。 そしお、これは基底のベクトルの次元が倧きいほど顕著で効果的です。 基底が128次元のベクトルで構成される堎合の結果は次のずおりです。



䞊列化


Mathematicaで䜕かを䞊行しお蚈算する方法


Mathematicaには、異なるコアで非同期蚈算を実行できる小さな関数セットがありたす。 今だけ甚語で定矩する必芁がありたす。 結局、実行䞭のプロセスは、Mathematicaの仮想マシンに䌌たものであり、カヌネルずも呌ばれたす。 カヌネル。 数孊の䞭栞は、むンタプリタモヌドで動䜜するむンタラクティブランタむムです。 各コアは、システム内の1぀のプロセスである必芁がありたす。 通垞の意味での蚀語はフロヌを実珟したせん。 したがっお、暙準䜿甚のコアには共有メモリがないこずを理解する必芁がありたす。 基本的に、このタむプのすべおの関数はParallelで始たりたす。 非同期的に䜕かをカりントする最も簡単な方法


 ParallelTable[i^2,{i, 1, 10}] (*Out[..] := {1, 4, 9, 16, 25, 36, 49, 64, 81, 100}*) 

倚くの機胜が同様に機胜したす。
ParallelMap 、 ParallelDo 、 ParallelProduct 、 ParallelSum 、...


これが実際に耇数のコアで実行されたこずを確認するには、いく぀かの方法がありたす。 これは、実行䞭のすべおのカヌネルを取埗する方法です。


 Kernels[] (* Out[..] := {"KernelObject"[1, "local"], ... , "KernelObject"[N, "local"]} *) 

リストには、珟圚実行䞭のすべおのプロセスが含たれたす。 同時に、タスクマネヌゞャヌにも衚瀺される必芁がありたす。



6぀のプロセスのうち2぀が実行䞭のセッションを担圓し、残りは䞊列コンピュヌティングに䜿甚されるロヌカルカヌネルです。 この堎合、デフォルトでは、ロヌカルMathematicaコアの数は物理プロセッサコアの数ず䞀臎したす。 しかし、だれも倧きな数を䜜成するこずを気にしたせん。 これはLaunchKernels [n]を䜿甚しお行われたす。 その結果、 远加の n個のコアが起動されたす。 たた、利甚可胜なプロセッサコアの数は、 $ KernelCount倉数で確認できたす。


最初にリストされた関数は、プロセス間でタスクを自動的に分散したす。 ただし、特定のカヌネルで実行するコヌドを個別に送信する方法がありたす。 これはParallelEvaluate + ParallelSubmitを䜿甚しお行われたす。


 ParallelEvaluate[$KernelID, Kernels[][[1 ;; 4 ;; 2]]] (* Out[..] := {1, 3}*) 

この䞀連の関数は、重みスペクトルの蚈算タスクを䞊列化するのに十分です。


メむンサむクルのパヌツぞの分離


蚈算が実際に䞊行しお行われるかどうかを確認したす。 4぀の物理コアの堎合、これは4぀のコアすべおの蚈算に1぀のコアず同じ時間がかかるこずを意味したす。


 basis = RandomInteger[{0, 1}, {24, 24}]; AbsoluteTiming[WeightSpectrumLinearSubspaceGrayCodeEasy[basis];][[1]] AbsoluteTiming[ParallelEvaluate[WeightSpectrumLinearSubspaceGrayCodeEasy[basis]];][[1]] (* Out[..] := 6.518... Out[..] := 8.790...*) 

時間差はありたすが、4倍ではありたせん。 これで、すべおがうたくいきたした。 次のステップは、タスクをいく぀かの郚分に分割する方法を理解するこずです。 最も論理的で効果的なのは、各コアで線圢結合の䞀郚のみを蚈算するこずです。 ぀たり、結果ずしお、各コアは郚分的なスペクトルを返したす。 しかし、リストb iを分割する方法。 結局のずころ、それは盎接的なシヌケンスではありたせん この堎合、むンデックスごずにグレむコヌドシヌケンスから倀を蚈算する関数が必芁です。 これは次のように行われたす。


 grayNum[basis_List, index_Integer] := IntegerDigits[BitXor[index, Quotient[index, 2]], 2, Length[basis]] Grid[Table[{i, Row[grayNum[{{0, 0}, {0, 1}, {1, 1}}, i]]}, {i, 0, 7}]] 

むンデックスコヌド
0000
1001
2011
3010
4110
5111
6101
7100

次に、線圢結合の特定の範囲のむンデックス内の郚分スペクトルのみを考慮するように、コンパむルされた関数を倉曎したす。


 WeightSpectrumLinearSubspaceGrayCodeRange = Compile[{{basis, _Integer, 2}, {range, _Integer, 1}}, Module[{ n = Dimensions[basis][[-1]], k = Length[basis], s = Table[0, {n + 1}], currentVector = Table[0, {i, 1, Length[basis[[1]]]}], m = 0, l = 0 }, (*     *) If[range[[1]] =!= 0, currentVector = Mod[Total[basis Reverse[IntegerDigits[BitXor[range[[1]], Quotient[range[[1]] + 1, 2]], 2, k]]], 2]; ]; Mod[Total[basis IntegerDigits[BitXor[range[[1]] - 1, Quotient[range[[1]] - 1, 2]], 2, k]], 2]; s[[Total[currentVector] + 1]] = 1; Do[ m = Log2[BitAnd[-1 - b, b + 1]] + 1; currentVector = BitXor[currentVector, basis[[m]]]; l = Total[currentVector] + 1; s[[l]] = s[[l]] + 1, {b, First[range], Last[range] - 1, 1} ]; (* Return *) s ], (*  ,       *) RuntimeOptions -> "Speed", (*CompilationTarget -> "C",*) CompilationOptions -> {"ExpressionOptimization" -> True} ]; 

぀たり、以前に関数が0〜2 N -1の番号を持぀すべおの組み合わせをカりントした堎合、この範囲は手動で蚭定できたす。 次に、䜿甚可胜なコアの数に応じお、この同じ範囲を等しい郚分に分割する方法を考えおみたしょう。


 partition[{i1_Integer, iN_Integer}, n_Integer] := With[{dn = Round[(iN - i1 + 1)/n]}, Join[ {{i1, i1 + dn - 1}}, Table[{dn * (i - 1), i * dn - 1}, {i, 2, n - 1}], {{(n - 1) * dn, iN}} ] ] 

ここで、そのような画像の完党なスペクトルを蚈算するには、各セグメントでそれを蚈算し、すべおの結果を远加する必芁がありたす。 䟋


 WeightSpectrumLinearSubspaceGrayCodeEasy[{{1, 1}, {1, 1}, {1, 1}}] WeightSpectrumLinearSubspaceGrayCodeRange[{{1, 1}, {1, 1}, {1, 1}}, {0, 3}] WeightSpectrumLinearSubspaceGrayCodeRange[{{1, 1}, {1, 1}, {1, 1}}, {4, 7}] (* Out[..] := {4, 0, 4} = Out[..] := {2, 0, 2} + Out[..] := {2, 0, 2} *) 

最埌のステップは、これらの蚈算を異なるカヌネルに送信するこずです。


 WeightSpectrumLinearSubspaceGrayCodeParallel[basis: {{__Integer}..}] := With[{ kernels = (If[Kernels[] === {}, LaunchKernels[]]; Kernels[]), parts = partition[{0, 2^Length[basis] - 1}, Length[Kernels[]]] }, Total[WaitAll[Table[ ParallelEvaluate[ParallelSubmit[WeightSpectrumLinearSubspaceGrayCodeRange[basis, parts[[$KernelID]]]], kernel], {kernel, kernels} ]]] ] 

ここで明確にする必芁がありたす。 このようなバンドルは、どのカヌネルがコヌドのどの郚分で実行されるかを手動で制埡するためのParallelEvaluate + ParallelSubmitです。 䞀般的な堎合のParallelEvaluateは、非同期コヌドを正しく実行する方法を理解できず、結果ずしお1぀のスレッドで実行したす。 たた、䞀般的なケヌスのParallelSubmitでは、正確なカヌネルを指定するこずはできたせんが、自動的に遞択したす。
この機胜が機胜するかどうかを確認したす。


 ListPlot[WeightSpectrumLinearSubspaceGrayCodeParallel[RandomInteger[{0, 1}, {16, 128}]], PlotRange -> All, PlotTheme -> "Web", Filling -> Bottom] 


そしおい぀ものように、蚈算速床の違いを芋おみたしょう。 4コアプロセッサを搭茉したラップトップが䜿甚されるため、加速は玄4倍になるず予想されたす。 さらに、タスクを分割しお最終結果を合蚈する時間を考慮する必芁がありたす。


 basis = RandomInteger[{0, 1}, {20, 1024}]; AbsoluteTiming[WeightSpectrumLinearSubspaceGrayCodeEasy[basis];] AbsoluteTiming[WeightSpectrumLinearSubspaceGrayCodeParallel[basis];] (* Out[..] := {5.02..., Null} Out[..] := {1.5....., Null} *) 

圓然、プロセッサコアの数が倚くなるず、違いはより顕著になりたす。 それでは、基底のスペクトルをさらに蚈算しおみたしょう。 どのくらい時間がかかるのだろうか 1぀の蚈算を完了するのに1分以䞊かかるたで、基底のサむズを倧きくするず仮定したす。


 spectrums = Block[{i = 1, basis, res}, Reap[ While[True, i++; basis = RandomInteger[{0, 1}, {i, i}]; Sow[res = AbsoluteTiming[WeightSpectrumLinearSubspaceGrayCodeParallel[basis]]]; If[res[[1]] > 60, Break[]] ] ][[-1, -1]]] ListPlot[spectrums[[-1, -1]], PlotLabel->Row[{"basis len: ", Length[spectrums] + 1, "; time: ", Round[spectrums[[-1, 1]], 0.01], " sec"}], Filling->Bottom,PlotTheme->"Web",PlotRange->All] 


この図は、関数が29のベクトルに基づいおスペクトルを1分半で蚈算できるこずを明確に瀺しおいたす。 これは、コンパむルを䜿甚しない最初のオプションであるグレむコヌド䞊列化が劥圓な時間内に同じこずを完了するこずができないため、非垞に良い結果です。 10次​​元の15個のベクトルでさえ蚈算に10秒以䞊かかった堎合、蚈算時間は数千倍になりたす。


おわりに


誰が、どこで蚘事に蚘茉されおいるすべおのものを適甚するのかわかりたせん。 りィキペディアによるず、グレむコヌドには実甚的な目的があるずのこずです。 たた、スペクトルの蚈算は、暗号化や線圢代数の他の問題に関連しおいるこずが倚いこずも知っおいたす。 , , : , . , .


PS , .

Source: https://habr.com/ru/post/J336350/


All Articles