📄 paralleliso.cxx
字号:
/*========================================================================= Program: Visualization Toolkit Module: $RCSfile: ParallelIso.cxx,v $ Language: C++ Date: $Date: 2002/09/30 20:37:43 $ Version: $Revision: 1.10 $ Copyright (c) 1993-2002 Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information.=========================================================================*/// This program demonstrates the use ports by setting up a simple // pipeline. All processes create an identical pipeline:// vtkImageReader -> vtkContourFilter -> vtkElevationFilter// In addition, the first (root) process creates n input ports// (where n=nProcs-1), each attached to an output port on the other // processes. It then appends the polygonal output from all input // ports and it's own pipeline and renders the result ISO_NUM times,// each time setting a different scalar value to be contoured.#include "vtkActor.h"#include "vtkAppendPolyData.h"#include "vtkCamera.h"#include "vtkContourFilter.h"#include "vtkDataSet.h"#include "vtkElevationFilter.h"#include "vtkImageData.h"#include "vtkImageReader.h"#include "vtkInputPort.h"#include "vtkMath.h"#include "vtkMultiProcessController.h"#include "vtkOutputPort.h"#include "vtkPolyData.h"#include "vtkPolyDataMapper.h"#include "vtkRenderWindow.h"#include "vtkRenderWindowInteractor.h"#include "vtkRenderer.h"#include "vtkTestUtilities.h"#include "vtkTimerLog.h"static const float ISO_START=4250.0;static const float ISO_STEP=-1250.0;static const int ISO_NUM=3;// Just pick a tag which is availablestatic const int ISO_VALUE_RMI_TAG=300; static const int PORT_TAG=999;// call back to set the iso surface value.void SetIsoValueRMI(void *localArg, void* vtkNotUsed(remoteArg), int vtkNotUsed(remoteArgLen), int vtkNotUsed(id)){ float val; vtkContourFilter *iso; iso = (vtkContourFilter *)localArg; val = iso->GetValue(0); iso->SetValue(0, val + ISO_STEP);}// This will be called by all processesvoid MyMain( vtkMultiProcessController *controller, void *arg ){ vtkImageReader *reader; vtkContourFilter *iso; vtkElevationFilter *elev; int myid, numProcs; float val; int numTris; char* fname = reinterpret_cast<char*>(arg); // Obtain the id of the running process and the total // number of processes myid = controller->GetLocalProcessId(); numProcs = controller->GetNumberOfProcesses(); // Create the reader, the data file name might have // to be changed depending on where the data files are. reader = vtkImageReader::New(); reader->SetDataByteOrderToLittleEndian(); reader->SetDataExtent(0, 63, 0, 63, 1, 93); reader->SetFilePrefix(fname); reader->SetDataSpacing(3.2, 3.2, 1.5); // Iso-surface. iso = vtkContourFilter::New(); iso->SetInput(reader->GetOutput()); iso->SetValue(0, ISO_START); iso->ComputeScalarsOff(); iso->ComputeGradientsOff(); // Compute a different color for each process. elev = vtkElevationFilter::New(); elev->SetInput(iso->GetOutput()); vtkMath::RandomSeed(myid * 100); val = vtkMath::Random(); elev->SetScalarRange(val, val+0.001); if (myid != 0) { // If I am not the root process // Satellite process! Send data through port. vtkOutputPort *upPort = vtkOutputPort::New(); // Last, set up a RMI call back to change the iso surface value. // This is done so that the root process can let this process // know that it wants the contour value to change. controller->AddRMI(SetIsoValueRMI, (void *)iso, ISO_VALUE_RMI_TAG); // connect the port to the output of the pipeline upPort->SetInput(elev->GetPolyDataOutput()); // Multiple ports can go through the same connection. // This is used to differentiate ports upPort->SetTag(PORT_TAG); // Loop which processes RMI requests. // Use vtkMultiProcessController::BREAK_RMI_TAG to break it. // The root process with send a ISO_VALUE_RMI_TAG to make this // process change it's contour value. upPort->WaitForUpdate(); // We are done. Clean up. upPort->Delete(); } else { // If I am the root process int i, j; vtkAppendPolyData *app = vtkAppendPolyData::New(); vtkInputPort *downPort; vtkRenderer *ren = vtkRenderer::New(); vtkRenderWindow *renWindow = vtkRenderWindow::New(); vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); vtkPolyDataMapper *mapper = vtkPolyDataMapper::New(); vtkActor *actor = vtkActor::New(); vtkTimerLog *timer = vtkTimerLog::New(); vtkCamera *cam = vtkCamera::New(); // Add my pipeline's output to the append filter app->AddInput(elev->GetPolyDataOutput()); // ###################### important #################### // # This tells the append filter to request pieces from // # each of its inputs. Since each of its inputs comes from // # a different process, each process generates a separate // # piece of the data (data parallelism). // # If this is not used, all processes will iso-surface // # all the data. app->ParallelStreamingOn(); // This is the main thread: Collect the data and render it. for (i = 1; i < numProcs; ++i) { downPort = vtkInputPort::New(); downPort->SetRemoteProcessId(i); // Multiple ports can go through the same connection. // This is used to differentiate ports downPort->SetTag(PORT_TAG); app->AddInput(downPort->GetPolyDataOutput()); // Reference already incremented by AddInput(). Delete() // will only decrement the count, not destroy the object. // The ports will be destroyed when the append filter // goes away. downPort->Delete(); downPort = NULL; } // Create the rendering part of the pipeline renWindow->AddRenderer(ren); iren->SetRenderWindow(renWindow); ren->SetBackground(0.9, 0.9, 0.9); renWindow->SetSize( 400, 400); mapper->SetInput(app->GetOutput()); actor->SetMapper(mapper); ren->AddActor(actor); cam->SetFocalPoint(100, 100, 65); cam->SetPosition(100, 450, 65); cam->SetViewUp(0, 0, -1); cam->SetViewAngle(30); cam->SetClippingRange(177.0, 536.0); ren->SetActiveCamera(cam); // loop through some iso surface values. for (j = 0; j < ISO_NUM; ++j) { // set the local value SetIsoValueRMI((void*)iso, NULL, 0, 0); for (i = 1; i < numProcs; ++i) { // trigger the RMI to change the iso surface value. controller->TriggerRMI(i, ISO_VALUE_RMI_TAG); } // Time the rendering. Note that the execution on all processes // start only after Update() timer->StartTimer(); app->Update(); timer->StopTimer(); numTris = iso->GetOutput()->GetNumberOfCells(); val = iso->GetValue(0); cerr << "Update " << val << " took " << timer->GetElapsedTime() << " seconds to produce " << numTris << " triangles\n"; // now render the results renWindow->Render(); } // Tell the other processors to stop processing RMIs. for (i = 1; i < numProcs; ++i) { controller->TriggerRMI(i, vtkMultiProcessController::BREAK_RMI_TAG); } // Clean up app->Delete(); ren->Delete(); renWindow->Delete(); iren->Delete(); mapper->Delete(); actor->Delete(); cam->Delete(); timer->Delete(); } // clean up objects in all processes. reader->Delete(); iso->Delete(); elev->Delete();}int main( int argc, char* argv[] ){ vtkMultiProcessController *controller; // Note that this will create a vtkMPIController if MPI // is configured, vtkThreadedController otherwise. controller = vtkMultiProcessController::New(); controller->Initialize(&argc, &argv); // Use this method to get the place of the data directory. char* fname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/headsq/quarter"); controller->SetSingleMethod(MyMain, reinterpret_cast<void*>(fname)); // When using MPI, the number of processes is determined // by the external program which launches this application. // However, when using threads, we need to set it ourselves. if (controller->IsA("vtkThreadedController")) { // Set the number of processes to 2 for this example. controller->SetNumberOfProcesses(2); } controller->SingleMethodExecute(); delete[] fname; controller->Finalize(); controller->Delete(); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -