読者です 読者をやめる 読者になる 読者になる

ローグウェーブソフトウェアのブログ

開発をシンプルに 安全で高品質のコードを 素早くお客様のもとへ

TotalViewのType Transformations機能

ローグウェーブの並列デバッガ TotalViewにはType Transformations (TTF、型変換)という便利な機能があります。

複雑なデータ構造をわかりやすく表示

C++などで構造体/クラスの入れ子や継承、テンプレートや配列などを駆使することにより、利用者側にとってわかりやすく抽象化されたクラスを作成することはよくあります。しかし、いざトラブルが発生したとき、あるいはシンプルなリストや配列だと思っていたデータ構造の値を単に眺めたいだけの時でも、想像もつかなかったような内部のデータ構造がデバッガによって表示され、必要な情報を得られずに戸惑うことになります。

例えば下の画像はSTLの通常のstd::vectorを表示させたものですが、通常は上のように背後にあるクラスの実装の詳細を表示するのではなく、下側の絵のようにシンプルな配列を得たいと思うことが多いでしょう。ここでは後に述べるSTLViewという技術が使われています。

f:id:RWSJapan:20160726155612p:plain

Type Transformationsは外部ファイルに、実装と論理的なデータ構造のマッピングを定義し、TotalViewに読み込ませることによって、そのクラスの利用者が想像していたようなわかりやすい表示を提示することができます。

ユーザ定義型とvectorを使ったサンプル

以下の様な、生年月日を表す3つの整数と生まれた国と都市、名前を表す3つの文字列から成るクラスを考えます。このクラスのインスタンス(Bach、Mozart、Boulez)をSTLvectorにpush_backします。

#include <cstdio>
#include <string>
#include <vector>

using std::string;
using std::vector;

class Customer {
public:
  Customer(int bm, int bd, int by, const string& name,
       const string& city, const string& country)
    : birth_month_(bm), birth_day_(bd), birth_year_(by),
      name_(name), city_(city), country_(country) { /* */ }
      
private:
  int birth_month_;
  int birth_day_;
  int birth_year_;
  string name_;
  string city_;
  string country_;
};


int main() {

  Customer bach(3,21,1685,"Johann Sebastian Bach","Eisenach","Holy Roman Empire");
  Customer mozart(1,27,1756,"Wolfgang Amadeus Mozart","Salzburg","Holy Roman Empire");
  Customer boulez(3,26,1925,"Pierre Boulez","Montbrison, Loire","France");

  vector<Customer> customers;
  customers.push_back(bach);
  customers.push_back(mozart);
  customers.push_back(boulez);
  
  return 0;
}

さて、ある開発中の用途として、たまたまこれらのデータのうち名前と生まれた年だけが知りたくなったとします。そんな時、以下の様なテキストファイル(stuff.tvdとします)を作成します。

::TV::TTF::RTF::build_struct_transform {
  name {^class Customer$}
  members {
    {customer_name { name_ } }
    {year { birth_year_ } }
  }
}

TotalViewのGUIを立ち上げてデバッグを開始した後、コマンドラインインターフェース CLIから

source stuff.tvd

を実行することにより、ユーザー定義型のうち必要な情報だけがデバッガで表示されるようになります。

実行ファイルが例えばcustomer.elfだった場合、customer.elfと同じフォルダに customer.elf.tvd というファイル名で上記のType Transformationを作成すると、source コマンドを発行する必要なく、TotalView起動時にこのファイルが読み込まれてカスタマイズされた表示が得られます。

紹介動画

HPC用ユーザーインターフェースによるもの youtu.be

newUI によるもの(CodeDynamicsも同様) youtu.be

Type Transformations (TTF)の詳細な作成方法はTotalviewユーザーガイドに記述されています。 PART I CLI Commands : Chapter 6 Creating Type Transformations

正規表現を使った実装のフィルタリングやポインタ表現、基底クラスへのキャストなどの説明や別のサンプルが記述されています。

STLView

このTTFの機能を使うと、STLやBoostなどのコンテナもわかりやすく表示することができます。記事冒頭のstd::vectorや、以下のstd:mapはその好例です。

STLViewオフのstd::map f:id:RWSJapan:20160726144344p:plain

STLViewオンのstd::map f:id:RWSJapan:20160726144352p:plain

実はTotalViewはデフォルトで多くのSTLコンテナに対応しており、8.14からはC++11で追加されたハッシュテーブル(unordered_map)などunordered_系のSTLも設定無しできれいに表示されます。 blog.roguewave.jp

必要なTVDファイルはインストールフォルダのlib以下に格納されており、起動時に必ず読み込まれます。なお、TotalViewは多くの環境に対応しているため、list一つを取ってみても、PGI、IntelGNU、XLCなど様々な処理系用にそれぞれTVDファイルが用意されています。

f:id:RWSJapan:20160726154424p:plain

STLViewについてもTotalviewユーザーガイドに記述がありますのでご覧ください。

PART II Debugging Tools and Tasks : Chapter 9 Examining and Editing Data and Program Elements : STLView

その他英語の説明による紹介動画もあります。

TotalView以外の実現例

また、同様の機能やカスタマイズ方法がgdbVisual Studioにも用意されているので、それぞれの処理系でどのようにプラグイン、マクロなどで対応しているのか比較してみるのも面白いと思います。

GDB

Visual Studio

C++View

複雑なデータ構造の表示を見やすくする手段として、TotalViewは上記のType Transformationの他に、C++Viewという手段も提供しています。こちらは外部設定ファイルではなくコードの中に直に変換方法を記述するもので、TotalViewには珍しくコードの変更が必要です。その代わり表示形式を非常に柔軟にカスタマイズすることが可能です。この機能の解説やType Transformationとの違いを以下に記しました。

blog.roguewave.jp

その他TotalViewの可視化機能

一方、クラスの入れ子や配列を含む複雑なデータ構造の表示方法についてはdive in allという機能もあり、クラスを要素とする配列の特定のメンバをあたかも一続きの配列であるかのように表示する方法です。デフォルトで使用可能です。

f:id:RWSJapan:20160727095618p:plain

動画で動作方法をご確認ください。 www.youtube.com

ローグウェーブ セールスエンジニア 柄澤 (からさわ)