This chapter describes how to examine the values of variables and expressions in your program. This is referred to as visualizing data. In addition, it describes how to find out the type of a variable and change its values.
See the following sections:
You can visualize either variables (including arrays, structures, pointers, etc.) or expressions; see " Writing Expressions in Prism" for information about writing expressions in Prism. In addition, you can provide a context, so that Prism handles the values of data elements differently, depending on whether they meet the condition you specify.
Prism provides two general methods for visualizing data: printing and displaying.
Printing data shows the value(s) of the data at a specified point during program execution.
Displaying data causes its value(s) to be updated every time the program stops execution.
Printing or displaying to the history region of the command window prints out the numeric or character values of the data in standard fashion.
Printing or displaying to a graphical window creates a visualizer, which provides you with various options as to how to represent the data.
Prism provides these methods for choosing what to print or display:
By choosing the Print or Display selection from the Debug menu in the menu bar (see " Printing and Displaying From the Debug Menu")
By selecting text within the source window (see " Printing and Displaying From the Source Window")
By adding events to the Event Table (see "Printing and Displaying From the Event Table")
By issuing commands from the command window (see " Printing and Displaying From the Command Window")
In all cases, choosing Display adds an event to the event list, since displaying data requires an action to update the values each time the program is stopped. Note that, since Display updates automatically, the only way to keep an unwanted display window from reappearing is to delete the corresponding display event.
You create print events only via the Event Table and the Events menu.
By default, Prism prints and displays values as decimal numbers. You can change this default by issuing the set $radix command, specifying as a setting 2 (binary), 8 (octal), or 16 (hexadecimal). For example,
set $radix = 16
changes the default representation to hexadecimal. To reset the default to decimal, issue the command
set $radix = 10
You can override the default for an individual print or display operation. See " Printing and Displaying From the Command Window" and " Using the Options Menu".
The default setting also affects the display of argument values in procedures in the call stack; see " Displaying the Call Stack".
Note these points in visualizing data:
You cannot print or display any variables after a program finishes execution.
Visualizers do not deal correctly with Fortran adjustable arrays. The size is determined when you create a visualizer for such an array. Subsequent updates to the visualizer will continue to use this same information, even though the size of the array may have changed since the last update. This will result in incorrect values in the visualizer. Printing or displaying values of an adjustable array in the command window or to a new window will work, however.
This section describes the methods Prism provides for printing and displaying data.
To print a variable or expression at the current program location, choose Print from the Debug menu. It is also by default in the tear-off region.
To display a variable or expression every time execution stops, starting at the current program location, choose Display from the Debug menu.
When you choose Print or Display, a dialog box appears; Figure 5-1 shows an example of the Print dialog box.
In the Expression box, enter the variable or expression whose value(s) you want printed. Text selected in the source window appears as the default; you can edit this text.
The dialog boxes also offer choices as to the window in which the values are to appear:
You can specify that the values are to be printed or displayed in a standard window dedicated to the specified expression. The first time you print or display the data, Prism creates this window. If you print data, and subsequently print it again, this standard window is updated. This is the default choice for both Print and Display.
You can create a separate snapshot window for printing or displaying values. This is useful if you want to compare values between windows.
You can print out the values in the command window.
Click on Print or Display to print the values of the specified expression at the current program location.
Click on Cancel or press the Esc key to close the window without printing or displaying.
To print and display from the source window:
Select the variable or expression by dragging over it with the mouse or double-clicking on it.
Right-click the mouse to display a pop-up menu.
Click on Print in this menu to display a snapshot visualizer containing the value(s) of the selected variable or expression at that point in the program's execution.
Click on Display to display a visualizer that is automatically updated whenever execution stops.
To print without bothering to display the menu, press the Shift key while selecting the variable or expression.
Prism prints the correct variable when you choose it in this way, even if the scope pointer sets a scope that contains another variable of the same name.
You can use the Events menu to define a print or display event that is to take place at a specified location in the program.
The Print dialog box (see Figure 5-2) prompts for the variable or expression whose value(s) are to be printed, the program location at which the printing is to take place, and the name of the window in which the value(s) are to be displayed.
Window names are dedicated, snapshot, and command; you can also make up your own name. The default is dedicated. See " Redirecting Output" for a discussion of these names.
When you have filled in the fields, click on OK; the event is added to the Event Table. When the location is reached in the program, the value(s) of the expression or variable are printed.
The Display dialog box is similar, but it does not prompt for a location; the display visualizer will update every time the program stops execution.
You can use the Event Table to define a print or display event that is to take place at a specified location in the program.
Click on Print or Display in the Common Events buttons to create an event that will print or display data.
If you click on Print, the Location and Action fields are highlighted. Put a program location in the Location field. Complete the print event in the Actions field, specifying the variable or expression, and the window in which it is to be printed. For example,
print d2 on dedicated
If you click on Display, the Location field displays stopped, and the Actions field displays print on dedicated. Complete the description of the print event, as described above. The variable or expression you specify is then displayed whenever the program stops execution.
Use the print command to print the value(s) of a variable or expression from the command window. Use the display command to display the value(s). The display command prints the value(s) of the variable or expression immediately, and creates a display event so that the values are updated automatically whenever the program stops.
The commands have this format:
[where (expression)] command variable[, variable ...]
The optional where (expression) syntax sets the context for printing the variable or expression; see below.
In the syntax, command is either print or display, and variable is the variable or expression to be displayed or printed.
Redirection of output to a window via the on window syntax works slightly differently for display and print from the way it works for other commands; see " Redirecting Output" for a discussion of redirection. Separate windows are created for each variable or expression that you print or display. Thus, the commands
display x on dedicated display y/4 on dedicated display [0:128:2]z on dedicated
create three windows, each of which is updated separately.
To print or display the contents of a register, precede the register's name with a dollar sign. For example,
print $pc
prints the program counter register. See " Displaying the Contents of Registers" for a list of register names supported by Prism.
You can precede the print or display command with a where statement that can make elements of a variable or array inactive. Inactive elements are not printed in the command window; " Overview of Data Visualization" describes how they are treated in visualizers. Making elements inactive is referred to as setting the context.
To set the context, follow the where keyword with an expression in parentheses. The expression must evaluate to true or false for every element of the variable or array being printed.
For example,
where (i .gt. 0) print i
prints (in the command window) only the values of i that are greater than 0.
You can use certain Fortran intrinsics in the where statement. For example,
where (a .eq. maxval(a)) print a
prints the element of a that has the largest value. (This is equivalent to the MAXLOC intrinsic function.) See " Writing Expressions in Prism" for more information on writing expressions in Prism.
Note that setting the context affects only the printing or displaying of the variable. It does not affect the actual context of the program as it executes.
You can specify the radix to be used in printing or displaying values by adding a suffix of the form /radix to the print or display command. radix can be b (binary), d (decimal), x (hexadecimal), or o (octal). For example,
print/b pvar1
prints the binary representation of pvar1 in the command window.
display/x pvar2 on dedicated
displays the hexadecimal values of pvar2 in a dedicated window.
The default radix is decimal, unless you have used the set $radix command to change it; see " Changing the Default Radix".
The window that contains the data being printed or displayed is called a visualizer. Figure 5-3 shows a visualizer for a 3-dimensional array.
The visualizer consists of two parts: the data navigator and the display window. There are also File and Options pulldown menus.
The data navigator shows which portion of the data is being displayed, and provides a quick method for moving through the data. The appearance of the data navigator depends on the number of dimensions in the data. It is described in more detail in " Using the Display Window in a Visualizer".
The display window is the main part of the visualizer. It shows the data, using a representation that you can choose from the Options menu. The default is text: that is, the data is displayed as numbers or characters. Figure 5-3 is a text visualizer. The display window is described in more detail in " Using the Options Menu".
The File menu lets you save, update, or cancel the visualizer; see " Using the File Menu" for more information. The Options menu, among other things, lets you change the way values are represented; see Section " Using the Options Menu".
The data navigator helps you move through the data being visualized. It has different appearances, depending on the number of dimensions in your data. If your data is a single scalar value, there is no data navigator.
For 1-dimensional arrays and parallel variables, the data navigator is the scroll bar to the right of the data. The number to the right of the buttons for the File and Options menus indicates the coordinate of the first element that is displayed. The elevator in the scroll bar indicates the position of the displayed data relative to the entire data set.
For 2-dimensional data, the data navigator is a rectangle in the shape of the data, with the axes numbered. The white box inside the rectangle indicates the position of the displayed data relative to the entire data set. You can either drag the box or click at a spot in the rectangle. The box moves to that spot, and the data displayed in the display window changes.
For 3-dimensional data, the data navigator consists of a rectangle and a slider, each of which you can operate independently. The value to the right of the slider indicates the coordinate of the third dimension. Changing the position of the bar along the slider changes which 2-dimensional plane is displayed out of the 3-dimensional data.
For data with more than three dimensions, the data navigator adds a slider for each additional dimension.
You can change the way the visualizer lays out your data by changing the numbers that label the axes. Click in the box surrounding the number; it is highlighted, and an I-beam appears. You can then type in the new number of the axis; you don't have to delete the old number. The other axis number automatically changes; for example, if you change axis 1 to 2, axis 2 automatically changes to become axis 1.
The display window shows the data being visualized.
In addition to using the data navigator to move through the data, you can drag the data itself relative to the display window by holding down the left mouse button; this provides finer control over the display of the data.
To find out the coordinates and value of a specific data element, click on it while pressing the Shift key. Its coordinates are displayed in parentheses, and its value is displayed beneath them. If you have set a context for the visualizer, you also see whether the element is active or inactive (see " Using the Options Menu"). Drag the mouse with the Shift key pressed, and you see the coordinates, value, and context of each data element over which the mouse pointer passes.
You can resize the visualizer to display more (or less) data either horizontally or vertically.
Click on File to pull down the File menu.
Choose Update from this menu to update the display window for this variable, using the value(s) at the current program location. See " Updating and Closing the Visualizer" for more information on updating a visualizer.
Choose Save or Save As to save the visualizer's values to a file. See " Saving the Values of a Variable" for more information.
Choose Diff or Diff With to compare the visualizer's values with values stored in a file. See " Comparing the Data" for more information.
Choose Snapshot to create a copy of the visualizer, which you can use to compare with later updates.
Choose Close to cancel the visualizer.
Click on Options to pull down the Options menu. See Figure 5-4.
Choose Representation from the Options menu to display another menu that gives the choices for how the values are represented in the display window. The choices are described below. You can control aspects of the way these visualizers appear by changing their parameters, as described later in this section.
Choose Histogram to display the values of an array or parallel variable in a histogram. See Figure 5-5 for an example.
The vertical axis displays the number of data points; the horizontal axis displays the range of values. Prism divides up this range evenly in creating the histogram bars. It prints summary data above the histogram.
Shift-click on a histogram bar to display the range and number of data points it represents.
Note that the histogram represents all the values of the variable, not just those shown in the 2-dimensional slice of data that happens to be displayed in other representations.
Choose Dither to display the values as a shading from black to white. Groups of values in a low range are assigned more black pixels; groups of values in a high range are assigned more white pixels. This has the effect of displaying the data in various shades of gray. Figure 5-6 shows a 2-dimensional dither visualizer. The lighter area indicates values that are higher than values in the surrounding areas; the darker area indicates values that are lower than surrounding values.
You can left-click on a histogram visualizer bar to get a pop-up window, showing its contents.
For complex numbers, Prism uses the modulus.
Choose Threshold to display the values as black or white. By default, Prism uses the mean of the values as the threshold; values less than or equal to the mean are black, and values greater than the mean are white. Figure 5-7 shows a threshold representation of a 3-dimensional array.
For complex numbers, Prism uses the modulus.
Choose Colormap (if you are using a color workstation) to display the values as a range of colors. By default, Prism displays the values as a continuous spectrum from blue (for the minimum value) to red (for the maximum value). You can change the colors that Prism uses; see " Changing Colors".
For complex numbers, Prism uses the modulus.
Choose Graph to display values as a graph, with the index of each array element plotted on the horizontal axis and its value on the vertical axis. A line connects the points plotted on the graph. This representation is particularly useful for 1-dimensional data, but can be used for higher-dimensional data as well; for example, in a 2-dimensional array, graphs are shown for each separate 1-dimensional slice of the 2-dimensional plane.
Figure 5-8 shows a graph visualizer for a 1-dimensional slice of an array.
Choose Surface (if your data has more than one dimension) to render the 3-dimensional contours of a 2-dimensional slice of data. In the representation, the 2-dimensional slice of data is tilted 45 degrees away from the viewer, with the top edge further from the viewer than the bottom edge. The data values rise out of this slice. Figure 5-1 is an example.
If there are large values in the top rows of the data, they may be drawn off the top of the screen. To see these values, flip the axes as described earlier in this section, so that the top row appears in the left column.
Choose Vector to display data as vectors. The data must be a Fortran complex or double complex number, or a pair of variables to which the CMPLX intrinsic function has been applied (see " Using Fortran Intrinsic Functions in Expressions"). The complex number is drawn showing both magnitude and direction. The length of the vector increases with magnitude. There is a minimum vector length of five pixels, because direction is difficult to see for smaller vectors. By default, the lengths of all vectors scale linearly with magnitude, varying between the minimum and maximum vector lengths. Figure 5-10 shows a vector visualizer.
Choose Parameters from the Options menu to display a dialog box in which you can change various defaults that Prism uses in setting up the display window; see Figure 5-11. If a parameter is grayed out or missing, it does not apply to the current representation.
The parameters (for all representations except the histogram representation) are:
Field Width - Type a value in this box to change the width of the field that Prism allocates to every data element.
For the text representation, the field width specifies the number of characters in each column. If a number is too large for the field width you specify, dots are printed instead of the number.
For dither, threshold, colormap, and vector representations, the field width specifies how wide (in pixels) the representation of each data element is to be. By default, dither, threshold, and colormap visualizers are scaled to fit the display window. Note, however, that for dither visualizers, the gray shading may be more noticeable with a smaller field width.
For the graph representation, the field width specifies the horizontal spacing between elements.
For the surface representation, it specifies the spacing of elements along both directions of the plane.
Precision - Type a value in this box to change the precision with which Prism displays real numbers in a text visualizer. The precision must be less than the field width. By default, Prism prints doubles with 16 significant digits, and floating-point values with 7 significant digits. You can change this default by issuing the set command with the $d_precision variable (for doubles) or $f_precision variable (for floating-point values). For example,
set $d_precision = 11
sets the default precision for doubles to 11 significant digits.
Minimum and Maximum - For colormap representations, use these variables to specify the minimum and maximum values that Prism is to use in assigning color values to the data elements. Data elements that have values below the minimum and above the maximum are assigned default colors.
For graph, surface, and vector representations, these parameters represent the bottom and top of the range that is to be represented. Values below the minimum are shown as the minimum; values above the maximum are shown as the maximum.
By default Prism uses the entire range of values for all these representations.
Threshold - For threshold representations, use this variable to specify the value at which Prism is to change the display from black to white. Data elements whose values are at or below the threshold are displayed as black; data elements whose values are above the threshold are displayed as white. By default, Prism uses the mean of the data as the threshold.
The parameters for the histogram representation are:
Bar Width - Specifies the width in pixels of each histogram bar (except for the bars representing infinities and NaNs, which must be wide enough to fit the Inf or NaN label underneath). The default is 10 pixels.
Bar Height - Specifies the height in pixels of the largest histogram bar. The default is 100 pixels.
Minimum - Specifies the minimum value to be included in the histogram. By default the actual minimum value is used.
Maximum- Specifies the maximum value to be included in the histogram. By default the actual maximum value is used.
If you specify a different minimum or maximum, values below the minimum or above the maximum are not displayed in the histogram, but are counted as outliers instead; the number of outliers is displayed above the histogram.
Max Buckets - Specifies the number of "buckets" into which values are to be poured--in other words, the number of histogram bars to be used. The default is 30. (Prism may use fewer to make the horizontal labels come out evenly.)
Choose Ruler from the Options menu to toggle the display of a ruler around the data in the display window. The ruler is helpful in showing which elements are being displayed. Figure 5-12 shows a 3-dimensional threshold visualizer with the ruler displayed.
In the surface representation, the ruler cannot indicate the coordinates of elements in the vertical axis, since they change depending on the height of each element. However, you can press the Shift key and left-click to display the coordinates and value of an element.
Choose Statistics from the Options menu to display a window containing statistics and other information about the variable being visualized. The window contains:
The name of the variable
Its type and number of dimensions
The total number of elements the variable contains, and the total number of active elements, based on the context you set within Prism (see the next section for a discussion of setting the context)
The variable's minimum, maximum, and mean; these statistics reflect the context you set for the visualizer
Figure 5-13 gives an example of the Statistics window.
For complex numbers, Prism uses the modulus.
Choose Set Context from the Options menu to display a dialog box in which you can specify which elements of the variable are to be considered active and which are to be considered inactive. Active and inactive elements are treated differently in visualizers:
In text, graph, surface, and vector visualizers, inactive elements are grayed out.
In colormap visualizers, inactive elements by default are displayed as gray. You can change this default; see " Changing Colors".
Context has no effect on dither and threshold visualizers.
Figure 5-14 shows the Set Context dialog box.
By default, all elements of the variable are active; this is the meaning of the everywhere keyword in the text-entry box. To change this default, you can either edit the text in the text-entry box directly or click on the Where button to display a menu. The choices in the menu are everywhere and other:
Choose everywhere, as mentioned above, to make all elements active.
Choose other to erase the current contents of the text-entry box. You can then enter an expression into the text-entry box.
In the text-entry box, you can enter any valid expression that will evaluate to true or false for each element of the variable.
The context you specify for printing does not affect the program's context; it just affects the way the elements of the variable are displayed in the visualizer.
See "Setting the Context" above for more information on context. See " Writing Expressions in Prism" for more information on writing expressions in Prism.
Click on Apply to set the context you specified. Click on Cancel or press the Esc key to close the dialog box without setting the context.
Choose Radix from the Options menu to change the radix used in the text representation of a value.
Choosing Radix pulls down a submenu with four selections: Decimal, Hex, Octal, and Binary. Choosing one of these changes the value to the specified radix. Prism continues to use this radix if the visualizer is updated.
By default, Prism displays values in decimal. You can change this default via the set $radix command; see " Changing the Default Radix". You can also override it for a specific print or display command; see " Printing and Displaying From the Command Window".
If you created a visualizer by issuing a display command, it automatically updates every time the program stops execution.
If you created the visualizer by issuing a print command, its display window is grayed out when the program resumes execution and the values in the window are outdated. To update the values, choose Update from the visualizer's File menu.
To close the visualizer, choose Close from the File menu, or press the Esc key.
You can save the values of a variable or expression to a file. You can subsequently visualize these values and compare them with the values in another visualizer--for example, the same variable later in the run, or during a totally separate execution of the program. This provides a convenient way of spotting changes in the values of a variable.
You can save the values of a variable or expression to a file for later use.
Use the command varsave to save the values of a variable or expression to a file. Its syntax is
varsave "filename" expression
where filename is the name of the file to which the data is to be saved, and expression is the variable or expression whose values are to be saved. For example,
varsave "alpha.data" alpha
saves the values of the variable alpha in the file alpha.data (in your current working directory within Prism).
varsave "/u/kathy/alpha2.data" alpha*2
saves the results of the expression alpha*2 in the file with the path name /u/kathy/alpha2.data.
Use the Save or Save As selection from a visualizer's File menu to save the visualizer's values to a file.
If you choose Save As, a dialog box appears in which you can specify the name of the file to which the values are to be saved; see Figure 5-15.
The highlighted directory is the current working directory. If you want to put the file there, simply type its name in the Save As box and click on OK.
If you want to put the file in another directory, click on the directory. (The parent directories of the current working directory are shown above it in the Directories list; its subdirectories are listed beneath it.) This will display the subdirectories of the directory you clicked on. You can traverse the directory structure in this manner until you find the directory in which you want to put the file, or, you can simply type the entire path name in the Save As box.
Choose the Save selection to save the values in the file you most recently specified. If you haven't specified a file, the values are saved in a file called noname.var in your current working directory in Prism.
Use the intrinsic varfile to bring values you have saved to a file back into Prism. Its syntax is:
varfile("filename")
where filename is the name of the file that contains the values you want to restore.
The varfile intrinsic is not available in MP Prism.
You can use the varfile intrinsic anywhere you could have used the original variable or expression that you saved to a file. For example, if you saved x:
varsave "x.var" x
then the command
print varfile("x.var")
is equivalent to
print x
Note that this allows you to save a variable's values, then print them during a later Prism session, without having a program loaded or running.
You can compare a variable or expression whose values have been saved in a file with another version of the variable or expression. This comparison could take place later in the same run of the program, during a subsequent run, or even during a second, simultaneous Prism session.
You can also compare the values with those of another variable, as long as both variables have the same base type (that is, you can't compare integers with floating-point numbers).
You can use the print or display command with the difference operator and the varfile intrinsic to perform a comparison between two versions of a variable or expression.
For example, if you saved x in the file x.var:
varsave "x.var" x
then the command
print x - varfile("x.var")
prints the difference between the current and saved values of x.
If an element is printed as 0, it is the same in both versions. If it is nonzero, its value is different in the two versions.
Use the Diff or Diff With selection from a visualizer's File menu to compare the visualizer's values with values stored in a file.
Choose Diff With to choose the file containing the values. It displays a dialog box like the one shown below.
The dialog box has the same format as the Save As dialog box described in " Saving the Values of a Variable". It lists the files found in your current working directory in Prism. Click on a file name, then click on OK to choose the file. Or type a file name in the Diff With text-entry box and click on OK.
Choose Diff to compare the visualizers values to those in the most recently specified file; if no file has been specified, values are compared to those in the file noname.var in your current working directory in Prism.
Once you have specified a file via Diff or Diff With, Prism creates a new visualizer that displays the difference in values between the visualizer and the file. If an element's value in the new visualizer is 0, the value is the same in both versions. If it is nonzero, it is different in the two versions.
You can work with this visualizer as you would any visualizer. For example, you can change the representation and display summary statistics.
Prism provides a layout intrinsic that returns the numbers of the nodes on which the data elements of a parallel object are located. Its syntax is
layout(pvar)
where pvar is a parallel object. You can use the Fortran 90 array-section syntax described in " Using Array-Section Syntax in C arrays " to specify a range of elements within a parallel object.
You can print or display the results of applying the layout intrinsic to a parallel object. For example,
print layout(p1) on dedicated
creates a visualizer that is the same size and shape as the parallel object p1. The visualizer displays the rank of the process that is holding each value.
Note that you can use other visualizer representations--for example, dither or colormap--to display the layout graphically.
If you print a pointer or a structure (or a structure-valued expression) in a window, a structure visualizer appears.
Figure 5-17 shows an example of a structure visualizer.
The structure you specified appears inside a box; this is referred to as a node. The node shows the fields in the structure and their values. If the structure contains pointers, small boxes appear next to them; they are referred to as buttons. Left-click on a node to select it. Use the up and down arrow keys to move between buttons of a selected node.
You can perform various actions within a structure visualizer, as described below.
You can expand scalar pointers in a structure to generate new nodes. (You cannot expand a pointer to a parallel variable.)
To expand a single pointer:
With a mouse - Left-click on a button to expand the pointer. For example, clicking on the button next to the nav field in Figure 5-17 changes the visualizer as shown in Figure 5-18.
From the keyboard - Use the right arrow key to expand and visit the node pointed to by the current button. If the node is already expanded, pressing the right arrow key simply visits the node. Use the left arrow key to visit the parent of a selected node.
To expand all pointers in a node:
With the mouse - Double-click or Shift-left-click on the node.
From the keyboard - Press the Shift key along with the right arrow key.
From the Options menu - Click on Expand. The cursor turns into a target; move the cursor to the node you are interested in and left-click.
To recursively expand all pointers from the selected node on down:
With the mouse - Triple-click or Control-left-click on the node.
From the keyboard - Press the Control key and the right arrow key.
From the Options menu - Click on Expand All. The cursor turns into a target; move the cursor to the node you are interested in and left-click.
You can left-click and drag through the data navigator or the display window to pan through the data, just as you can with visualizers; see " Using the Data Navigator in a Visualizer" and " Using the Display Window in a Visualizer".
You can also "zoom" in and out on the data by left-clicking on the Zoom arrows. Click on the down arrow to zoom out and see a bird's-eye view of the structure; click on the up arrow to get a closeup. Figure 5-19 shows part of a complicated structure visualizer after zooming out.
Left-click on a node in a zoomed-out structure visualizer to pop up a window showing the full contents of the node.
The selected node is centered in the display window whenever you zoom in or out.
To delete a node (except the root node):
With the mouse - Middle-click on a node (except the root node).
From the Options menu - Click on Delete. The cursor turns into a target; move the cursor to the node you want to delete and left-click.
Deleting a node also deletes its children (if any).
Note the following about pointers in structure visualizers:
Null pointers--have "ground" symbols next to them.
If you have previously expanded a pointer, it has an arrow next to its button; you cannot expand the pointer again. (This prevents infinite loops on circular data structures.)
A pointer containing a bad address has an X drawn over its button.
You may provide a special function for each of your data types that makes additional information available to Prism. This enables Prism to more accurately display the contents of structures with that data type.
For C or C++ union types, you may identify which member of the union is valid. For a pointer within a structure, you may specify that the pointer's target is an array of elements, rather than a single element, and you may further specify the length of the array.
You must embed these specifications within a special function that is compiled and linked with your program being debugged. The function has the following form:
void prism_define_typename (typename *ptr);
where typename is the tag name of one of your structure data types. Thus, you can define one such function for each of your data types. When Prism displays a variable of this type, it checks whether an augmentation function is defined in the program. If so, Prism calls the function, passing a pointer to the instance of the structure being displayed. Your function may then look at the instance to choose valid union members and to size dynamic arrays.
You communicate this information back to Prism by calling the following, defined in prism.h:
void prism_add_array(char *member_name, int len);
This call specifies that the pointer named member_name points to an array of length len. The pointer's name, member_name, is the name of one of the members of the structure, as found in the structure's C (or C++) declaration. The results are undefined if member_name is not a pointer.
void prism_add_union(char *name, char *valid_member);
This call specifies that the member named name is of type union, and of all the members of this union, only valid_member is to be displayed. Both name and valid_member are names as found in the C or C++ declarations of structs or unions.
Assume that data in the declaration below is a dynamic array:
struct Vector { int len; int *data; };
The function you write looks like this:
#include "prism.h" void prism_define_Vector(struct Vector *v) { prism_add_array("data", v->len); }
Assume that the member type discriminates the union value in this example:
enum Type {INT, DOUBLE}; struct Value { enum Type type; union { int i; double d; } value; };
The function you write would look like this:
#include "prism.h" void prism_define_Value(struct Value *val) { if (val->type == INT) prism_add_union("value", "i"); else prism_add_union("value", "d"); }
There are no restrictions on the number or order of calls to prism_add_union and prism_add_array.
Left-click on Update in the File menu to update a structure visualizer. When you do this, the root node is re-read; Prism attempts to expand the same nodes that are currently expanded. (The same thing happens if you re-print an existing structure visualizer.)
Left-click on Close in the File menu to close the structure visualizer.
Prism provides several methods for finding out the type of a variable.
From the menu bar - Choose the Whatis selection from the Debug menu. The Whatis dialog box appears; it prompts for the name of a variable. Click on Whatis to display the information about the variable in the command window.
From the source window - Select a variable by double-clicking on it or by dragging over it while pressing the left mouse button. Then hold down the right mouse button; a pop-up menu appears. Choose Whatis from this menu. Information about the variable appears in the command window.
From the command window - Issue the whatis command from the command line, specifying the name of the variable as its argument.
Prism displays the information about the variable in the command window. For example,
whatis primes logical primes(1:999)
You can use the assign command to assign new values to a variable or an array. For example,
assign x = 0
assigns the value 0 to the variable x. You can put anything on the left-hand side of the statement that can go on the left-hand side in the language you are using-- for example, a variable or a Fortran array section.
If the right-hand side does not have the same type as the left-hand side, Prism performs the proper type coercion.
Use the command value = base to change the radix of a value in Prism. The value can be a decimal, hexadecimal, or octal number. Precede hexadecimal numbers with 0x; precede octal numbers with 0 (zero). The base can be D (decimal), X (hexadecimal), or O (octal). Prism prints the converted value in the command window.
For example, to convert 100 (hex) to decimal, issue this command:
0x100=D
Prism responds:
256
Use the dump command, followed by the name of a function or procedure, to print the names and values of all local variables in that function or procedure. If you omit the function name, dump uses the current function. If you specify a period, dump prints the names and values of all local variables in the functions in the stack.
Prism allows you to print simple arrays by section. For example, assuming the following declarations and code,
double da[]={0.1,1.1,2.1,3.1,4.1,5.1,6.1,7.1,8.1,9.1,10.1}; double *pd=da; int a[]={0,1,2,3,4,5,6,7,8,9,10}; int *pa=a; int *par[10]; int **ppi=par; void *ptr=(void*)da; ... for(i=0;i<10;i++) par[i]=&a[9-i]; <------ assume that the program is stopped here ------ ... |
you can print array a by section:
print a[1:5:2] a[1:5:2] = (1:3) 1 3 5
Prism allows you to view a pointer as a one-dimensional array, by specifying a section when printing the pointer. For example:
print pa[1:5:2] pa[1:5:2] = (1:3) 1 3 5
Prism allows you to dereference an array of pointers if you specify the elements to be dereferenced by using sections. If the array element is a pointer, then Prism allows you to the dereference the section:
*par[1:5:2] = (1:3) 8 6 4
Prism allows you to cast pointers:
print ((double*)ptr)[1:4:2] ((double*)ptr)[1:4:2] = (1:2) 1.100000000000000 3.100000000000000
Currently, Prism supports only one level of dereferencing. Assuming this declaration:
int **appi[2];
Prism does not support:
print **(appi[0:1])
Although Prism allows one level of dereference for sections, Prism does not support indexing. Thus, Prism allows:
print *par[1:5:2]
but Prism does not allow:
print par[1:5:2][0]
When you print or display an object in MP Prism, the data is shown for all processes in the pset you specify (in the current pset, if you do not include a pset qualifier). Choosing the Print or Display selection from the Debug menu prints or displays data for processes in the current pset.
If there is only one process in the pset, the visualizer that is displayed is no different from the visualizer you would see in scalar Prism.
If there is more than one process in the pset, Prism adds a dimension to the visualizer. The extra dimension represents the processes in the set. For example, if the variable is scalar, Prism displays a 1-dimensional array that represents the value of the variable in each process. If you are printing a 1-dimensional array, Prism uses a 2-dimensional visualizer.
For C programs, axis 0 represents the processes. For Fortran 77 programs, the highest-numbered axis represents the processes.
Prism can aggregate data from multiple processes only if the expression has the same size and number of dimensions in each process; if it doesn't, Prism prints an error message.
In the example shown in Figure 5-20, the variable board is an 8x8 array (representing a chess board); the current pset contains four processes. Therefore, MP Prism displays a 3-dimensional visualizer. Axis 0 represents the processes. The figure shows the values of board in the first process in the set. You would drag the white bar in the slider portion of the data navigator to display the values in the other processes in the set. (Note that, for a 2-dimensional Fortran array, where axis 3 would represent the processes, you might want to rearrange the display axes so that axis 3 is on the slider. You can do this by clicking in the box to the left of the slider and changing the number to a 3.)
To find out the value and process number for an element, shift-click on the element.
Printing to the history region, or in commands-only Prism, works the same way. Axis 0 represents the processes. Here is some of the history-region output for the data shown below:
(prism all) print board board = process 0 (0,0,0:4) 4 1 0 3 0 (0,0,5:7) -1 0 -4 (0,1,0:4) 2 1 0 0 0 (0,1,5:7) 0 -1 0 (0,2,0:4) 3 1 0 0 0 (0,2,5:7) 2 -1 -3 (0,3,0:4) 5 0 0 0 -1 (0,3,5:7) 0 0 -5 (0,4,0:4) 4 0 0 -2 0 (0,4,5:7) 0 0 -6 (0,5,0:4) 0 1 0 0 0 (0,5,5:7) 0 -1 0 (0,6,0:4) 0 1 0 0 0 (0,6,5:7) 0 -1 0 (0,7,0:4) 6 -1 0 0 0 (0,7,5:7) 0 -1 -4 process 1 (1,0,0:4) 4 1 0 3 0 (1,0,5:7) -1 0 -4 (1,1,0:4) 2 1 0 1 0 ... |
The elements of axis 0 do not necessarily correspond to the numbers of the processes they represent. For example, if you were visualizing a variable in pset (1, 3, 5, 7), element 0 of axis 0 would represent process 1, element 1 would represent process 3, and so forth.
MP Prism provides a Cycle visualizer window you can use to display the values of a variable in the cycle pset; see " The cycle Pset". If you issue the command
print x on cycle
Prism displays a window containing the value of x in the current process of the current pset. If you then issue the cycle command or otherwise cycle through the members of the cycle pset, this window automatically updates to display the value of x in the next member of the set. This provides a convenient way of examining a variable in a series of processes.
Use the Prism MPI queue visualizer to examine the message queues created by your Sun MPI program. The visualizer shows you the status of messages generated by nonblocking send and receive routines that have not been reaped by a call to MPI_Test or MPI_Wait.
By showing you the state of the queue, detailing the messages that have not completed, Prism gives you clues regarding where your program's logic can be tuned.
The Prism queue visualizer also shows you unexpected receive routines, indicating performance or correctness problems:
Performance - An unexpected receive indicates the receipt of a message before a posted matching receive; an extra copy of the message may be incurred.
Correctness - An unexpected receive can arise due to an intended receive not having been posted or having been posted incorrectly, such as with the wrong tag. The program may deadlock due to errors.
In addition to viewing the status of messages, you can also view the contents of the messages themselves to ensure that the correct data was transmitted.
Prism does not display blocking sends and receives on message queues. If a blocking routine such as an MPI_Send hangs your program, you can use Prism to display a stack backtrace to find the problem, showing the MPI_Send present on the stack. Prism also does not display MPI generalized requests.
To launch the MPI queue visualizer, choose the MPI Msgs selection under the Prism Debug menu. This selection is available only when a program linked to the Sun MPI library has been loaded into Prism. See Figure 5-23 for an example.
Each row of messages displayed in the message queue window corresponds to a process rank, numbered from zero. The following sections describe how each part of the MPI queue visualizer window affects the display of messages.
Use the View menu to select the queues to visualize. You can view three classes of MPI queues for each rank:
Posted Sends
Posted Receives
Unexpected Receives
You can view queues only when a rank has stopped. Otherwise, the visualizer displays the label running for that rank. Prism re-evaluates the queue every time the rank stops.
The MPI queue visualizer opens, by default at zoom level three. Using the Zoom buttons, you can zoom through four levels of message detail. The levels are:
Examples of the zoom levels are:
Figure 5-21 shows a single pixel per message. This zoom level is useful when examining very large MPI jobs.
Figure 5-22 shows a simple box per message (the size of the box increases with the size of the message).
Figure 5-23 shows a single label on message. Clicking the buttons on the Show menu toggles the labels. Label choices are Source/Destination and Tag.
Figure 5-24 shows the entire message.
Use the toggle buttons under Show on the MPI queue visualizer to control the value of the message labels. Select Source/Dest to show the source or destination rank for the message; select Tag to show the MPI tag of the message. The Show toggle affects the display of messages at zoom level three only.
You can sort messages by row or by column according to several criteria, by choosing selections from the Sort Rows By and Sort Columns By option menus.
Table 5-1 Column Sort Criteria
Sort Criteria |
Description |
---|---|
Order posted |
Sort messages by the order in which messages are posted by the MPI program, with the earliest posted on the left. This is the default. The implementation of MPI Sends of large messages may queue and dequeue the message several times once the rendezvous begins, at which point the posted order seen in the visualizer no longer matches the programmatic order. At present there is no way to distinguish such messages. |
Source/Destination |
Sort by the source rank for receives and the destination rank for sends. |
Tag |
Sort by the messages' tag values. |
Size |
Sort by size in bytes, from small to large. |
Communicator |
Sort by communicator address. |
Protocol |
Group together messages sent with the same transport protocol. Protocols are loopback, shared memory, RSM, and TCP. |
Table 5-2 Row Sort Criteria
Sort Criteria |
Description |
---|---|
Rank |
Sort rows from the smallest to the largest process rank (the default). |
Message Count |
Sort by the number of messages posted. |
Message Volume |
Sort by the sum of the sizes, in bytes, of all messages for each rank. |
Since the graphical size of a message is not linearly proportional to the message length in bytes, a number of small messages may occasionally extend further to the right in the visualizer than a single large message of greater total size.
Click individual messages to open the Message dialog box, shown in Figure 5-25.
The fields in the Message dialog box are described in Table 5-3.
Table 5-3 Message Dialog Box Fields
Label |
Description |
---|---|
Buffer |
The address of the message. |
Size |
The length (in bytes) of the message. |
Tag |
The MPI tag argument passed in the call to post the message. |
Comm |
The name of the MPI communicator in which the message belongs, or the communicator's address if it is unnamed. Click on the Communicator View button to display the Communicator dialog box. |
To |
The rank of the destination of the message. Prism displays this field only for posted sends. |
From |
The rank of the sender of the message. Prism displays this field only for posted receives or unexpected receives. |
Protocol |
The implementation method by which the message has been sent. Possible values are: loopback, shared memory, RSM, and TCP. |
Data Type |
The MPI data type of the message, with the size of a single data type element in bytes. Click on the Data Type View button to display the Data Type dialog box. See "Data Types" for more information about the Data Type dialog box.The View button is available only for user-defined data types. |
Contents |
The contents of the message. Click on the triangular button to open or close the contents area. Click on More repeatedly to scroll through more of the message, until the whole message has been displayed. |
When the Message dialog box displays a posted receive, it displays the value of the buffer address as null (indicating that no buffer has been allocated), and disables the Contents button.
When the Message dialog box displays an unexpected receive, it shows the delivered message with no data type. This characteristic is due to MPI design, since a posted receive declares the data type. Here too, the Contents button is disabled, and the visualizer displays the value of the buffer address as null.
Prism displays MPI Communicators in the Communicators region of the MPI queue visualizer window. The visualizer does not display all the communicators that have been created in an MPI program; rather, it displays only communicators referenced by currently posted messages. Thus, if no messages are visible, then the visualizer displays no communicators.
Prism displays as many as three distinct communicators. Each communicator is color coded, and messages are drawn using the color of their communicator. If more than three communicators are present, then the excess are grouped together under a single color labeled Others.
You can change colors for the communicators by setting the following X resources in the Prism application defaults file:
Prism.comm1Color
Prism.comm2Color
Prism.comm3Color
Prism.commOtherColor
For information about modifying values in the Prism applications defaults file, see " Changing Prism Defaults".
Figure 5-26 shows the Communicator dialog box. Press any of the communicator buttons to reveal the Communicator dialog box, displaying the following information:
Name
Address - The address of the communicator.
Fortran handle - The Fortran identifier for the communicator, if defined. Built in communicators such as MPI_COMM_WORLD have predefined Fortran handles. Other communicators are assigned a Fortran handle only if they are used in a Fortran subroutine.
Topology - The options are:
Cartesian - Communicators created using MPI_Cart_create.
Graph - Communicators created using MPI_Graph_create.
None - All others.
Size - The number of ranks.
Remote Size - Shown only for intercommunicators; the size of the remote group (the number of ranks). For information about intercommunicators, see the MPI_Intercomm_create man page.
Ranks - The list of ranks, possibly annotated with job identifiers if the communicator was created via an MPI client/server rendezvous or an MPI_Spawn. The ranks displayed for a communicator are relative to MPI_COMM_WORLD, rather than relative to the communicator's parent.
Figure 5-27 shows the Data Type dialog box. Display the Data Type dialog box by clicking on the Data Type View button in a Message dialog box. The fields of this dialog box are:
Type - The description of the data type, such as "struct" or "contiguous."
Address - The address of the corresponding MPI_Datatype object in the MPI program.
Size - The size in bytes of a single element of this data type.
Contiguous - An indication that the bytes of this data type are contiguous and may be sent or received without any intermediate packing or unpacking. If the data type is not contiguous, the label changes to Non-contiguous.
Additional information that is specific to the data type, representing arguments that were passed to MPI to create the data type. This may include offsets, block sizes, pointers to other data types, and so forth. In this example, Displacement, Blocklength, and Oldtype refer to arguments the programmer used when creating the MPI struct data type. Click on buttons that name other data types to display the Data Type dialog box for that other type.
In a multiprocess Sun MPI program, a parallel array is an array whose elements may be distributed among the processes of the program (every process holds only part of the global array). Prism can extract the global dimensionality and distribution information from these arrays and manipulate them as single entities. For the purpose of this discussion, arrays that are not distributed (arrays that belong in their entirety to a single process) are referred to as regular arrays.
Sun S3L's parallel array syntax is based on array handles, which define the properties of the parallel array. Using Prism's type command to identify a Sun S3L array handle and specify its basic data type, you can use Prism to display and visualize the Sun S3L parallel array.
Basic data types are int, float, double, complex8, and complex16. Before using the type command, Prism recognizes the array handle as a simple variable. In Fortran 77 and Fortran 90, the array handle is a variable of type integer*8. In C, the array handle is type S3L_array_t.
Table 5-4 S3L Array Demonstration Program
c c Copyright (c) 1998, by Sun Microsystems, Inc. c All rights reserved c |
program test_prism_s3l |
c |
include 's3l/s3l-f.h' |
c c In f77 programs, s3l arrays are integer*8 c |
integer*8 a |
c |
integer*4 ext(2),local(2),ier |
c |
c Initialize the S3L library and the prism/s3l interface. |
c |
call s3l_init(ier) |
|
c c Declare a parallel S3L array of size 2 x 3, c with the second dimension distributed. |
c |
ext(1) = 2 |
ext(2) = 3 |
|
local(1) = 1 |
local(2) = 0 |
|
call s3l_declare(a,2,ext,S3L_float,local, |
.S3L_USE_MALLOC,ier) |
|
c c Initialize the array randomly by using S3L_rand_lcg c |
|
call s3l_rand_lcg(a,123456,ier) |
w = 1.0 |
c c free the resources associated with the parallel S3L array
|
call s3l_free(a,ier) |
|
c finalize the S3L library. |
|
call s3l_exit(ier) |
c |
stop end |
For example, before using the type command, the whatis command reports that the Sun S3L array handle, a, has been declared an integer*8 in the Fortran program in Table 5-4.
Before applying the Prism type command, Prism identifies the array handle, a, as a variable of type integer*8:
(prism all) whatis a integer*8 a
Issue the type command, associating the Sun S3L handle, a, with the basic data type float, the same type used to declare the element type of the Sun S3L array in your program:
(prism all) type float a "a" defined as "float a"
Now Prism recognizes a as a Sun S3L handle and can call the appropriate Sun S3L routines to get the array's data and extents.
(prism all) type float a "a" defined as "float a"
Prism now recognizes a as a Sun S3L array. You can now use Prism to display the values of a using the print command:
(prism all) print a a = (0:1,0) 0.000000 1.000000 (0:1,1) 0.1000000 1.100000 (0:1,2) 0.2000000 1.200000
In all respects, you can use a as you would use any array in Prism. For example:
You can use a as an array variable:
(prism all) assign a=9 (prism all) print a a = (0:1,0) 9.000000 9.000000 (0:1,1) 9.000000 9.000000 (0:1,2) 9.000000 9.000000
You can use a to gather information on where the elements of a are distributed:
(prism all) print layout a layout (a) = a = (0:1,0) 0 0 (0:1,1) 0 0 (0:1,2) 1 1
You can launch Prism's visualizers to display a graphically. For example, to launch a visualizer window:
(prism all) print layout(a) on dedicated
Sun S3L arrays are distributed across multiple processes. Since each process has an identical view of a, Prism prints the values of the array only once.
However, when Prism prints a regular array, larr,Prism prints the values of larr separately for each process. For regular arrays such as larr, the values of the array can be different on different processes, since every process has its own copy. For example:
(prism all) print larr larr = Pset 0 (1:2,1,1) 0.000000 1.000000 (1:2,2,1) 0.1000000 1.100000 (1:2,3,1) 0.2000000 1.200000 Pset 1 (1:2,1,2) 0.000000 1.000000 (1:2,2,2) 0.1000000 1.100000 (1:2,3,2) 0.2000000 1.200000 (prism all) assign larr=larr*5 pset 0 (prism all) print larr larr = Pset 0 (1:2,1,1) 0.000000 5.000000 (1:2,2,1) 0.5000000 5.500000 (1:2,3,1) 1.000000 6.000000 Pset 1 (1:2,1,2) 0.000000 1.000000 (1:2,2,2) 0.1000000 1.100000 (1:2,3,2) 0.2000000 1.200000
Expressions involving Sun S3L arrays (after having issued the type command), unless they include a variable in the user program, are printed only once. Their values are the same for all processes:
(prism all) print 10* a - 1 10* a - 1 = (0:1,0) -1.000000000000000 9.000000000000000 (0:1,1) 0.00000000000000000 10.00000023841858 (0:1,2) 1.000000029802322 11.00000047683716 (prism all) print a a = (0:1,0) 0.000000 1.000000 (0:1,1) 0.1000000 1.100000 (0:1,2) 0.2000000 1.200000
However, if you use a Sun S3L array in an expression that includes a variable, then Prism replicates the array on each process and then evaluates the array separately on each process. This example adds a variable, w, to a. Prism prints the results for both processes.
(prism all) print w w = (1:2) 0 0 (prism all) print a+w a+w = Pset 0 (0:1,0,1) 0.000000000000000 1.000000000000000 (0:1,1,1) 0.1000000014901161 1.100000023841858 (0:1,2,1) 0.2000000029802322 1.200000047683716 Pset 1 (0:1,0,2) 0.000000000000000 1.000000000000000 (0:1,1,2) 0.1000000014901161 1.100000023841858 (0:1,2,2) 0.2000000029802322 1.200000047683716