Have an amazing solution built in RAD Studio? Let us know. Looking for discounts? Visit our Special Offers page!
DelphiRAD Studio

並列配列と順番付きディクショナリによるDelphi RTLの高速化

faster-delphi-rtl

RAD Studio 12.2では、多くの新機能の追加や多数の機能強化が行われています。そのうちDelphi ランタイム ライブラリ (RTL) の分野にも注目すべき機能強化がいくつか行われております。

新しいTParallelArray クラス

System.Threadingユニットには、配列項目に対して &ForSortなどの処理を並列実行できる新しいTParallelArrayクラスが追加されました。マルチコアシステムでは、これにより処理速度が大幅に向上します。

では、この新しいクラスをどのように使用するのでしょうか?

本ブログでは、2つの同一の配列を作成し、通常のシングルスレッドのSortと新しい並列バージョンでソートするコマンドラインプロジェクトを例に簡単なテストケースをご紹介いたします。

program ParallelArray;
 
{$APPTYPE CONSOLE}
 
{$R *.res}
 
uses
  System.SysUtils,
  System.Classes,
  System.Generics.Collections,
  System.Threading,
  System.Diagnostics;
 
var
  A1, A2: array of Integer;
  I: Integer;
  T: TStopwatch;
 
begin
  try
    SetLength(A1, 100_000_000);
    SetLength(A2, 100_000_000);
    for I := 0 to High(A1) do
    begin
      A1[I] := Random(MaxInt);
      A2[I] := A1[I];
    end;
 
    // Warm up thread pool
    TTask.Create(
      procedure
      begin
        // empty
      end).Start;
 
    // Serial sorting
    T := TStopwatch.StartNew;
    TArray.Sort(A1);
    T.Stop;
    Writeln('TArray.Sort: ', T.Elapsed.ToString);
 
    // Parallel sorting
    T := TStopwatch.StartNew;
    TParallelArray.Sort(A2);
    T.Stop;
    Writeln('TParallelArray.Sort: ', T.Elapsed.ToString);
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

今回テストケースの検証のために使用したCPUのスペックは、(Intel(R) Core(TM) i7-10700 CPU @ 2.90GHz) で、このPC環境で実行したところ、585%の改善という素晴らしい結果が得られました。(読みやすくするために出力はミリ秒単位に切り詰められています)

TArray.Sort: 00:00:16.414
TParallelArray.Sort: 00:00:02.889

新しいTOrderedDictionary クラス

System.Generics.Collectionsユニットには、TDictionaryから派生した新しいTOrderedDictionaryクラスが追加されました。このOrdered Dictionaryという順番付きディクショナリは、ディクショナリ内にソート メソッドが統合されたディクショナリクラスです。このクラスを使用することによって、ソートされた順序でデータをナビゲートするfor inループを簡単に作成でき、要素の検索も高速化されます。

例として、以下の手順で実行するプロジェクトをご覧ください。

  • 順番付きディクショナリを作成し、いくつかの要素を追加する
  • 出力と、1億回キーを検索するのにかかった時間を表示する
  • キーでソートし、再度出力を表示し、1億回の検索呼び出しを繰り返す (はるかに高速です!)
  • 値でソートし、再度表示する
  • 要素を追加する。並べ替え順序で要素が追加されていないことを証明するには、必要に応じて並べ替える必要があります (複数の要素を挿入する場合は、通常、この方が高速です)
program OrderedDictionaryDemo;
 
{$APPTYPE CONSOLE}
 
{$R *.res}
 
uses
  System.SysUtils,
  System.Generics.Collections,
  System.Diagnostics;
 
var
  T: TStopwatch;
 
begin
  try
    var ODict := TOrderedDictionary .Create;
    ODict.Add ('one', 'London');
    ODict.Add ('two', 'Berlin');
    ODict.Add ('three', 'Rome');
    ODict.Add ('four', 'Athens');
    ODict.Add ('five', 'Madrid');
    ODict.Add ('six', 'Bruxelles');
    ODict.Add ('seven', 'Paris');
 
    writeln ('Natural');
    for var APair in ODict do
      writeln (APair.Key + ' - ' + APair.Value);
    T := TStopwatch.StartNew;
    for var I := 0 to 100_000_000 do
      ODict.IndexOf('five');
    T.Stop;
    Writeln('IndexOf unsorted: ', T.Elapsed.ToString);
    writeln;
 
    writeln ('SortByKeys');
    ODict.SortByKeys;
    for var APair in ODict do
      writeln (APair.Key + ' - ' + APair.Value);
    T := TStopwatch.StartNew;
    for var I := 0 to 100_000_000 do
      ODict.IndexOf('five');
    T.Stop;
    Writeln('IndexOf sorted: ', T.Elapsed.ToString);
    writeln;
 
    writeln ('SortByValues');
    ODict.SortByValues;
    for var APair in ODict do
      writeln (APair.Key + ' - ' + APair.Value);
    writeln;
 
    writeln ('SortByValues plus extra item');
    ODict.Add ('eight', 'Prague');
    for var APair in ODict do
      writeln (APair.Key + ' - ' + APair.Value);
    writeln;
 
    readln;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

出力結果は、以下の通りです。

Natural
one - London
two - Berlin
three - Rome
four - Athens
five - Madrid
six - Bruxelles
seven - Paris
IndexOf unsorted: 00:00:01.2720716
 
SortByKeys
five - Madrid
four - Athens
one - London
seven - Paris
six - Bruxelles
three - Rome
two - Berlin
IndexOf sorted: 00:00:00.6366114
 
SortByValues
four - Athens
two - Berlin
six - Bruxelles
one - London
five - Madrid
seven - Paris
three - Rome
 
SortByValues plus extra item
four - Athens
two - Berlin
six - Bruxelles
one - London
five - Madrid
seven - Paris
three - Rome
eight - Prague

RTLのさらなる機能強化

  • TRegistryクラスは、rdMultiStringのサポートが改善され、新しいメソッド ReadNoneおよびWriteNone(Windowsのレジストリ値の型であるREG_NONEにマップ)が追加されました。
  • System.DateUtilsのRFC822形式の日付のサポートが改善されました。
  • RAD Studioに同梱されているDelphiランタイムパッケージ向けのマップファイルが提供されるようになりました。

今回のブログは以上となります。RAD Studio 12.2で追加された多くの新しいRTL機能を、ぜひプロジェクトで活用してください。

Kai for RAD Studio is Now Available! Special Live Webinar: Introducing Kai - A New Chapter for RAD Studio RAD Studio 13.1 Florence Now Available

Reduce development time and get to market faster with RAD Studio, Delphi, or C++Builder.
Design. Code. Compile. Deploy.

Start Free Trial   Upgrade Today

   Free Delphi Community Edition   Free C++Builder Community Edition

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

IN THE ARTICLES