| 29 | const int mpiRank, const int mpiWorldSize, box3f &bounds); |
| 30 | |
| 31 | int main(int argc, char **argv) |
| 32 | { |
| 33 | int mpiThreadCapability = 0; |
| 34 | MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &mpiThreadCapability); |
| 35 | if (mpiThreadCapability != MPI_THREAD_MULTIPLE |
| 36 | && mpiThreadCapability != MPI_THREAD_SERIALIZED) { |
| 37 | fprintf(stderr, |
| 38 | "OSPRay requires the MPI runtime to support thread " |
| 39 | "multiple or thread serialized.\n"); |
| 40 | return 1; |
| 41 | } |
| 42 | |
| 43 | int mpiRank = 0; |
| 44 | int mpiWorldSize = 0; |
| 45 | MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank); |
| 46 | MPI_Comm_size(MPI_COMM_WORLD, &mpiWorldSize); |
| 47 | |
| 48 | std::cout << "OSPRay rank " << mpiRank << "/" << mpiWorldSize << "\n"; |
| 49 | |
| 50 | // load the MPI module, and select the MPI distributed device. Here we |
| 51 | // do not call ospInit, as we want to explicitly pick the distributed |
| 52 | // device |
| 53 | auto OSPRAY_MPI_DISTRIBUTED_GPU = |
| 54 | utility::getEnvVar<int>("OSPRAY_MPI_DISTRIBUTED_GPU").value_or(0); |
| 55 | if (OSPRAY_MPI_DISTRIBUTED_GPU) { |
| 56 | ospLoadModule("mpi_distributed_gpu"); |
| 57 | } else { |
| 58 | ospLoadModule("mpi_distributed_cpu"); |
| 59 | } |
| 60 | |
| 61 | { |
| 62 | cpp::Device mpiDevice("mpiDistributed"); |
| 63 | mpiDevice.commit(); |
| 64 | mpiDevice.setCurrent(); |
| 65 | |
| 66 | // set an error callback to catch any OSPRay errors and exit the application |
| 67 | ospDeviceSetErrorCallback( |
| 68 | mpiDevice.handle(), |
| 69 | [](void *, OSPError error, const char *errorDetails) { |
| 70 | std::cerr << "OSPRay error: " << errorDetails << std::endl; |
| 71 | exit(error); |
| 72 | }, |
| 73 | nullptr); |
| 74 | |
| 75 | // all ranks specify the same rendering parameters, with the exception of |
| 76 | // the data to be rendered, which is distributed among the ranks |
| 77 | box3f regionBounds; |
| 78 | cpp::Instance spheres = |
| 79 | makeLocalSpheres(mpiRank, mpiWorldSize, regionBounds); |
| 80 | |
| 81 | // create the "world" model which will contain all of our geometries |
| 82 | cpp::World world; |
| 83 | world.setParam("instance", cpp::CopiedData(spheres)); |
| 84 | |
| 85 | /* |
| 86 | * Note: We've taken care that all the generated spheres are completely |
| 87 | * within the bounds, and we don't have ghost data or portions of speres |
| 88 | * to clip off. Thus we actually don't need to set region at all in |
nothing calls this directly
no test coverage detected