Commit d98154fe authored by Kenneth Moreland's avatar Kenneth Moreland
Browse files

Merge branch 'MaxImageSplit'

parents 9b6039e9 ffb78ee2
......@@ -40,7 +40,7 @@ OPTION(ICET_USE_MPI "Build MPI communication layer for IceT." ON)
# Option to set the preferred K value to use in the radix-k algorithm
SET(initial_magic_k 8)
IF ("${CMAKE_SYSTEM_NAME}" MATCHES "^BlueGene")
SET(initial_magic_k 32)
SET(initial_magic_k 16)
ENDIF ("${CMAKE_SYSTEM_NAME}" MATCHES "^BlueGene")
IF ("$ENV{ICET_MAGIC_K}" GREATER 1)
SET(initial_magic_k $ENV{ICET_MAGIC_K})
......@@ -52,6 +52,15 @@ IF (NOT ${ICET_MAGIC_K} GREATER 1)
MESSAGE(SEND_ERROR "ICET_MAGIC_K must be set to a number greater than 1.")
ENDIF (NOT ${ICET_MAGIC_K} GREATER 1)
# Option to set the preferred number of ways to break up an image.
SET(initial_max_image_split 512)
IF ("$ENV{ICET_MAX_IMAGE_SPLIT}" GREATER 0)
SET(initial_max_image_split $ENV{ICET_MAX_IMAGE_SPLIT})
ENDIF ("$ENV{ICET_MAX_IMAGE_SPLIT}" GREATER 0)
SET(ICET_MAX_IMAGE_SPLIT ${initial_max_image_split} CACHE STRING
"Sets the preferred number of times an image may be split. Some image compositing algorithms prefer to partition the images such that each process gets a piece. Too many partitions, though, and you end up spending more time collecting them than you save balancing the compositing."
)
# Configure MPE support
IF (ICET_USE_MPI)
OPTION(ICET_USE_MPE "Use MPE to trace MPI communications. This is helpful for developers trying to measure the performance of parallel compositing algorithms." OFF)
......
......@@ -58,7 +58,7 @@ ICET_INTERLACE_IMAGES
icetSparseImageInterlace
ICET_MAGIC_K environment variable
ICET_MAGIC_K environment variable, cmake variable, state variable
ICET_COLLECT_TIME: The fraction of ICET_COMPOSITE_TIME spent in collecting
image fragments to display process.
......@@ -94,3 +94,5 @@ processes contain all pixels in the image (ICET_VALID_PIXELS_OFFSET is 0
and ICET_VALID_PIXELS_NUM is the number of pixels in the image), and all
other processes have no pixel data. Strategies taking advantage of turning
off ICET_COLLECT_IMAGES should set this.
ICET_MAX_IMAGE_SPLIT environment variable, cmake variable, state variable
......@@ -2410,26 +2410,36 @@ static IceTImage getRenderBuffer(void)
/* Check to see if we are in the same frame as the last time we returned
this buffer. In that case, just restore the buffer because it still has
the image we need. */
if ( icetStateGetTime(ICET_RENDER_BUFFER_SIZE)
if ( icetStateGetTime(ICET_RENDER_BUFFER_HOLD)
> icetStateGetTime(ICET_IS_DRAWING_FRAME) ) {
/* A little bit of hackery: this assumes that a buffer initialized is the
same one returned from icetImagePackageForSend. It (currently)
does. */
IceTVoid *buffer;
icetRaiseDebug("Last render should still be good.");
buffer = icetGetStateBuffer(ICET_RENDER_BUFFER, 0);
icetGetPointerv(ICET_RENDER_BUFFER_HOLD, &buffer);
return icetImageUnpackageFromReceive(buffer);
} else {
IceTInt dim[2];
IceTImage image;
IceTVoid *buffer;
IceTSizeType dummy_size;
icetGetIntegerv(ICET_PHYSICAL_RENDER_WIDTH, &dim[0]);
icetGetIntegerv(ICET_PHYSICAL_RENDER_HEIGHT, &dim[1]);
/* Creating a new image object. "Touch" the ICET_RENDER_BUFFER_SIZE state
variable to signify the time we created the image so the above check
works on the next call. */
/* Create a new image object. */
image = icetGetStateBufferImage(ICET_RENDER_BUFFER, dim[0], dim[1]);
/* Record image size and pointer to memory. It is important to "touch"
ICET_RENDER_BUFFER_HOLD to signify the time we created the image so
that the above check works on the next call. */
icetStateSetIntegerv(ICET_RENDER_BUFFER_SIZE, 2, dim);
return icetGetStateBufferImage(ICET_RENDER_BUFFER, dim[0], dim[1]);
icetImagePackageForSend(image, &buffer, &dummy_size);
icetStateSetPointer(ICET_RENDER_BUFFER_HOLD, buffer);
return image;
}
}
......@@ -170,6 +170,21 @@ void icetStateSetDefaults(void)
icetStateSetInteger(ICET_MAGIC_K, ICET_MAGIC_K_DEFAULT);
}
if (getenv("ICET_MAX_IMAGE_SPLIT") != NULL) {
IceTInt max_image_split = atoi(getenv("ICET_MAX_IMAGE_SPLIT"));
if (max_image_split > 0) {
icetStateSetInteger(ICET_MAX_IMAGE_SPLIT, max_image_split);
} else {
icetRaiseError("Environment variable ICET_MAX_IMAGE_SPLIT must be"
" set to an integer greater than 0.",
ICET_INVALID_VALUE);
icetStateSetInteger(ICET_MAX_IMAGE_SPLIT,
ICET_MAX_IMAGE_SPLIT_DEFAULT);
}
} else {
icetStateSetInteger(ICET_MAX_IMAGE_SPLIT, ICET_MAX_IMAGE_SPLIT_DEFAULT);
}
icetStateSetPointer(ICET_DRAW_FUNCTION, NULL);
icetStateSetPointer(ICET_RENDER_LAYER_DESTRUCTOR, NULL);
......@@ -651,7 +666,11 @@ IceTVoid *icetGetStateBuffer(IceTEnum pname, IceTSizeType num_bytes)
if ( (icetStateGetType(pname) == ICET_VOID)
&& (icetStateGetNumEntries(pname) >= num_bytes) ) {
/* A big enough buffer is already allocated. */
return icetUnsafeStateGet(pname, ICET_VOID);
IceTVoid *buffer = icetUnsafeStateGet(pname, ICET_VOID);
#ifdef ICET_STATE_CHECK_MEM
memset(buffer, 0xDC, num_bytes);
#endif
return buffer;
}
/* Check to make sure this state variable has not been used for anything
......
......@@ -281,6 +281,7 @@ ICET_EXPORT void icetDiagnostics(IceTBitField mask);
#define ICET_FRAME_COUNT (ICET_STATE_ENGINE_START | (IceTEnum)0x002E)
#define ICET_MAGIC_K (ICET_STATE_ENGINE_START | (IceTEnum)0x0040)
#define ICET_MAX_IMAGE_SPLIT (ICET_STATE_ENGINE_START | (IceTEnum)0x0041)
#define ICET_DRAW_FUNCTION (ICET_STATE_ENGINE_START | (IceTEnum)0x0060)
#define ICET_RENDER_LAYER_DESTRUCTOR (ICET_STATE_ENGINE_START|(IceTEnum)0x0061)
......@@ -307,7 +308,8 @@ ICET_EXPORT void icetDiagnostics(IceTBitField mask);
#define ICET_RENDERED_VIEWPORT (ICET_STATE_FRAME_START | (IceTEnum)0x0010)
#define ICET_RENDER_BUFFER (ICET_STATE_FRAME_START | (IceTEnum)0x0011)
#define ICET_RENDER_BUFFER_SIZE (ICET_STATE_FRAME_START | (IceTEnum)0x0012)
#define ICET_TILE_PROJECTIONS (ICET_STATE_FRAME_START | (IceTEnum)0x0013)
#define ICET_RENDER_BUFFER_HOLD (ICET_STATE_FRAME_START | (IceTEnum)0x0013)
#define ICET_TILE_PROJECTIONS (ICET_STATE_FRAME_START | (IceTEnum)0x0014)
#define ICET_STATE_TIMING_START (IceTEnum)0x000000C0
......
......@@ -123,7 +123,8 @@ typedef IceTInt64 IceTPointerArithmetic;
#error "Unexpected pointer size."
#endif
#define ICET_MAGIC_K_DEFAULT @ICET_MAGIC_K@
#define ICET_MAGIC_K_DEFAULT @ICET_MAGIC_K@
#define ICET_MAX_IMAGE_SPLIT_DEFAULT @ICET_MAX_IMAGE_SPLIT@
#cmakedefine ICET_USE_MPE
......
This diff is collapsed.
......@@ -20,6 +20,7 @@ SET(MyTests
CompressionSize.c
Interlace.c
OddImageSizes.c
OddProcessCounts.c
RadixkUnitTests.c
SimpleTiming.c
SparseImageCopy.c
......
/* -*- c -*- *****************************************************************
** Copyright (C) 2011 Sandia Corporation
** Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
** the U.S. Government retains certain rights in this software.
**
** This source code is released under the New BSD License.
**
** This tests how compositing behaves when given process counts that have
** been known to cause problems in the past.
*****************************************************************************/
#include <IceT.h>
#include "test_codes.h"
#include "test-util.h"
#include <IceTDevCommunication.h>
#include <IceTDevState.h>
#include <stdlib.h>
#include <stdio.h>
static void draw(const IceTDouble *projection_matrix,
const IceTDouble *modelview_matrix,
const IceTFloat *background_color,
const IceTInt *readback_viewport,
IceTImage result)
{
IceTUByte *color_buffer;
IceTSizeType num_pixels;
IceTSizeType i;
/* Suppress compiler warnings. */
(void)projection_matrix;
(void)modelview_matrix;
(void)background_color;
(void)readback_viewport;
num_pixels = icetImageGetNumPixels(result);
color_buffer = icetImageGetColorub(result);
for (i = 0; i < num_pixels*4; i++) {
color_buffer[i] = 255;
}
}
static int OddProcessCountsTryFrame(void)
{
IceTDouble identity[16];
IceTFloat black[4];
identity[ 0] = 1.0;
identity[ 1] = 0.0;
identity[ 2] = 0.0;
identity[ 3] = 0.0;
identity[ 4] = 0.0;
identity[ 5] = 1.0;
identity[ 6] = 0.0;
identity[ 7] = 0.0;
identity[ 8] = 0.0;
identity[ 9] = 0.0;
identity[10] = 1.0;
identity[11] = 0.0;
identity[12] = 0.0;
identity[13] = 0.0;
identity[14] = 0.0;
identity[15] = 1.0;
black[0] = black[1] = black[2] = 0.0f;
black[3] = 1.0f;
/* For now, just invoke a frame and see if it crashes. May want to
check for image correctness later. */
icetDrawFrame(identity, identity, black);
icetCommBarrier();
return TEST_PASSED;
}
static int OddProcessCountsTryCollectOptions(void)
{
IceTInt si_strategy;
icetGetIntegerv(ICET_SINGLE_IMAGE_STRATEGY, &si_strategy);
if (si_strategy == ICET_SINGLE_IMAGE_STRATEGY_RADIXK) {
IceTInt rank;
IceTInt num_proc;
IceTInt magic_k;
icetGetIntegerv(ICET_RANK, &rank);
icetGetIntegerv(ICET_NUM_PROCESSES, &num_proc);
for (magic_k = 2; magic_k <= num_proc; magic_k *= 2) {
IceTInt max_image_split;
if (rank == 0) {
printf(" Using magic k value of %d\n", magic_k);
}
icetStateSetInteger(ICET_MAGIC_K, magic_k);
for (max_image_split = 0;
max_image_split <= num_proc;
max_image_split += magic_k) {
IceTInt result;
if (rank == 0) {
printf(" Using image split of %d\n",
max_image_split);
}
icetStateSetInteger(ICET_MAX_IMAGE_SPLIT, max_image_split);
result = OddProcessCountsTryFrame();
if (result != TEST_PASSED) { return result; }
}
}
return TEST_PASSED;
} else {
return OddProcessCountsTryFrame();
}
}
static int OddProcessCountsTryStrategy(void)
{
IceTInt rank;
int single_image_strategy_index;
icetGetIntegerv(ICET_RANK, &rank);
/* Only iterating over single image strategies. We are specifically using
the reduce strategy to simulate smaller process groups. Besides, the
single image strategies generally have more complicated indexing for odd
process counts. */
for (single_image_strategy_index = 0;
single_image_strategy_index < SINGLE_IMAGE_STRATEGY_LIST_SIZE;
single_image_strategy_index++) {
int result;
IceTEnum single_image_strategy =
single_image_strategy_list[single_image_strategy_index];
icetSingleImageStrategy(single_image_strategy);
if (rank == 0) {
printf(" Using %s single image sub-strategy.\n",
icetGetSingleImageStrategyName());
}
result = OddProcessCountsTryCollectOptions();
if (result != TEST_PASSED) { return result; }
}
return TEST_PASSED;
}
static int OddProcessCountsTryCount(void)
{
IceTInt rank;
IceTInt max_proc;
IceTInt mid_proc;
IceTInt add_proc;
IceTInt last_add_proc;
/* Use the reduce strategy to simulate using a certain process count. */
icetStrategy(ICET_STRATEGY_REDUCE);
icetGetIntegerv(ICET_RANK, &rank);
icetGetIntegerv(ICET_NUM_PROCESSES, &max_proc);
mid_proc = 1;
while (mid_proc < max_proc) { mid_proc *= 2; }
mid_proc /= 2;
last_add_proc = add_proc = 1;
while (mid_proc + add_proc <= max_proc) {
IceTInt num_proc = mid_proc + add_proc;
IceTInt result;
if (rank == 0) {
printf(" Using %d processes\n", num_proc);
}
if ((max_proc - rank) <= num_proc) {
/* In visible range. */
icetBoundingBoxd(-1.0, 1.0,
-1.0, 1.0,
-1.0, 1.0);
} else {
/* Outside of visible range. */
icetBoundingBoxd(100000.0, 100001.0,
100000.0, 100001.0,
100000.0, 100001.0);
}
result = OddProcessCountsTryStrategy();
if (result != TEST_PASSED) { return result; }
{
IceTInt next_add_proc = last_add_proc + add_proc;
last_add_proc = add_proc;
add_proc = next_add_proc;
}
}
return TEST_PASSED;
}
static int OddProcessCountsRun(void)
{
IceTInt num_proc;
IceTInt *process_ranks;
IceTInt proc;
icetGetIntegerv(ICET_NUM_PROCESSES, &num_proc);
icetCompositeMode(ICET_COMPOSITE_MODE_BLEND);
icetSetColorFormat(ICET_IMAGE_COLOR_RGBA_UBYTE);
icetSetDepthFormat(ICET_IMAGE_DEPTH_NONE);
icetDisable(ICET_CORRECT_COLORED_BACKGROUND);
icetDrawCallback(draw);
icetResetTiles();
icetAddTile(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, num_proc-1);
process_ranks = malloc(num_proc * sizeof(IceTInt));
for (proc = 0; proc < num_proc; proc++) {
process_ranks[proc] = proc;
}
icetEnable(ICET_ORDERED_COMPOSITE);
icetCompositeOrder(process_ranks);
free(process_ranks);
return OddProcessCountsTryCount();
}
int OddProcessCounts(int argc, char *argv[])
{
/* To remove warning. */
(void)argc;
(void)argv;
return run_test(OddProcessCountsRun);
}
......@@ -90,6 +90,8 @@ static IceTEnum g_strategy;
static IceTEnum g_single_image_strategy;
static IceTBoolean g_do_magic_k_study;
static IceTInt g_max_magic_k;
static IceTBoolean g_do_image_split_study;
static IceTInt g_min_image_split;
static float g_color[4];
......@@ -97,24 +99,26 @@ static void usage(char *argv[])
{
printf("\nUSAGE: %s [testargs]\n", argv[0]);
printf("\nWhere testargs are:\n");
printf(" -tilesx <num> Sets the number of tiles horizontal (default 1).\n");
printf(" -tilesy <num> Sets the number of tiles vertical (default 1).\n");
printf(" -frames Sets the number of frames to render (default 2).\n");
printf(" -seed <num> Use the given number as the random seed.\n");
printf(" -transparent Render transparent images. (Uses 4 floats for colors.)\n");
printf(" -tilesx <num> Sets the number of tiles horizontal (default 1).\n");
printf(" -tilesy <num> Sets the number of tiles vertical (default 1).\n");
printf(" -frames Sets the number of frames to render (default 2).\n");
printf(" -seed <num> Use the given number as the random seed.\n");
printf(" -transparent Render transparent images. (Uses 4 floats for colors.)\n");
printf(" -colored-background Use a color for the background and correct as necessary.\n");
printf(" -no-interlace Turn off the image interlacing optimization.\n");
printf(" -no-collect Turn off image collection.\n");
printf(" -sync-render Synchronize rendering by adding a barrier to the draw callback.\n");
printf(" -write-image Write an image on the first frame.\n");
printf(" -reduce Use the reduce strategy (default).\n");
printf(" -vtree Use the virtual trees strategy.\n");
printf(" -sequential Use the sequential strategy.\n");
printf(" -bswap Use the binary-swap single-image strategy.\n");
printf(" -radixk Use the radix-k single-image strategy.\n");
printf(" -tree Use the tree single-image strategy.\n");
printf(" -magic-k-study Use the radix-k single-image strategy and repeate for multiple\n"
" values of k.\n");
printf(" -no-interlace Turn off the image interlacing optimization.\n");
printf(" -no-collect Turn off image collection.\n");
printf(" -sync-render Synchronize rendering by adding a barrier to the draw callback.\n");
printf(" -write-image Write an image on the first frame.\n");
printf(" -reduce Use the reduce strategy (default).\n");
printf(" -vtree Use the virtual trees strategy.\n");
printf(" -sequential Use the sequential strategy.\n");
printf(" -bswap Use the binary-swap single-image strategy.\n");
printf(" -radixk Use the radix-k single-image strategy.\n");
printf(" -tree Use the tree single-image strategy.\n");
printf(" -magic-k-study <num> Use the radix-k single-image strategy and repeat for\n"
" multiple values of k, up to <num>, doubling each time.\n");
printf(" -max-image-split-study <num> Repeat the test for multiple maximum image\n"
" splits starting at <num> and doubling each time.\n");
printf(" -h, -help Print this help message.\n");
printf("\nFor general testing options, try -h or -help before test name.\n");
}
......@@ -137,6 +141,8 @@ static void parse_arguments(int argc, char *argv[])
g_single_image_strategy = ICET_SINGLE_IMAGE_STRATEGY_AUTOMATIC;
g_do_magic_k_study = ICET_FALSE;
g_max_magic_k = 0;
g_do_image_split_study = ICET_FALSE;
g_min_image_split = 0;
for (arg = 1; arg < argc; arg++) {
if (strcmp(argv[arg], "-tilesx") == 0) {
......@@ -180,6 +186,11 @@ static void parse_arguments(int argc, char *argv[])
g_single_image_strategy = ICET_SINGLE_IMAGE_STRATEGY_RADIXK;
arg++;
g_max_magic_k = atoi(argv[arg]);
} else if (strcmp(argv[arg], "-max-image-split-study") == 0) {
g_do_image_split_study = ICET_TRUE;
g_single_image_strategy = ICET_SINGLE_IMAGE_STRATEGY_RADIXK;
arg++;
g_min_image_split = atoi(argv[arg]);
} else if ( (strcmp(argv[arg], "-h") == 0)
|| (strcmp(argv[arg], "-help")) ) {
usage(argv);
......@@ -816,6 +827,7 @@ static int SimpleTimingDoRender()
timings_type *timing_collection = malloc(num_proc*sizeof(timings_type));
const char *strategy_name;
const char *si_strategy_name;
IceTInt max_image_split;
strategy_name = icetGetStrategyName();
if (g_single_image_strategy == ICET_SINGLE_IMAGE_STRATEGY_RADIXK) {
......@@ -829,6 +841,8 @@ static int SimpleTimingDoRender()
si_strategy_name = icetGetSingleImageStrategyName();
}
icetGetIntegerv(ICET_MAX_IMAGE_SPLIT, &max_image_split);
for (frame = 0; frame < g_num_frames; frame++) {
timings_type *timing = &timing_array[frame];
......@@ -857,7 +871,7 @@ static int SimpleTimingDoRender()
total_bytes_sent += timing_collection[p].bytes_sent;
}
printf("LOG,%d,%s,%s,%d,%d,%d,%d,%s,%s,%s,%d,%lg,%lg,%lg,%lg,%lg,%lg,%lg,%lg,%ld,%lg\n",
printf("LOG,%d,%s,%s,%d,%d,%d,%d,%s,%s,%s,%d,%d,%lg,%lg,%lg,%lg,%lg,%lg,%lg,%lg,%ld,%lg\n",
num_proc,
strategy_name,
si_strategy_name,
......@@ -868,6 +882,7 @@ static int SimpleTimingDoRender()
g_transparent ? "yes" : "no",
g_no_interlace ? "no" : "yes",
g_no_collect ? "no" : "yes",
max_image_split,
frame,
timing->render_time,
timing->buffer_read_time,
......@@ -913,6 +928,7 @@ int SimpleTimingRun()
"transparent,"
"interlacing,"
"collection,"
"max image split,"
"frame,"
"render time,"
"buffer read time,"
......@@ -954,6 +970,42 @@ int SimpleTimingRun()
if (retval != TEST_PASSED) { return retval; }
}
return TEST_PASSED;
} else if (g_do_image_split_study) {
IceTContext original_context = icetGetContext();
IceTInt num_proc;
IceTInt magic_k;
IceTInt image_split;
icetGetIntegerv(ICET_NUM_PROCESSES, &num_proc);
icetGetIntegerv(ICET_MAGIC_K, &magic_k);
for (image_split = g_min_image_split;
image_split/magic_k < num_proc;
image_split *= magic_k) {
char image_split_string[32];
int retval;
sprintf(image_split_string, "%d", image_split);
setenv("ICET_MAX_IMAGE_SPLIT", image_split_string, ICET_TRUE);
/* This is a bit hackish. The max image split value is set when the
IceT context is initialized. Thus, for the environment to take
effect, we need to make a new context. (Another benefit:
resetting buffers.) To make a new context, we need to get the
communiator. */
{
IceTCommunicator comm = icetGetCommunicator();
icetCreateContext(comm);
}
retval = SimpleTimingDoRender();
/* We no longer need the context we just created. */
icetDestroyContext(icetGetContext());
icetSetContext(original_context);
if (retval != TEST_PASSED) { return retval; }
}
return TEST_PASSED;
} else {
return SimpleTimingDoRender();
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment