| 42 | VolumeBrick makeLocalVolume(const int mpiRank, const int mpiWorldSize); |
| 43 | |
| 44 | int main(int argc, char **argv) |
| 45 | { |
| 46 | int mpiThreadCapability = 0; |
| 47 | MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &mpiThreadCapability); |
| 48 | if (mpiThreadCapability != MPI_THREAD_MULTIPLE |
| 49 | && mpiThreadCapability != MPI_THREAD_SERIALIZED) { |
| 50 | fprintf(stderr, |
| 51 | "OSPRay requires the MPI runtime to support thread " |
| 52 | "multiple or thread serialized.\n"); |
| 53 | return 1; |
| 54 | } |
| 55 | |
| 56 | int mpiRank = 0; |
| 57 | int mpiWorldSize = 0; |
| 58 | MPI_Comm_rank(MPI_COMM_WORLD, &mpiRank); |
| 59 | MPI_Comm_size(MPI_COMM_WORLD, &mpiWorldSize); |
| 60 | |
| 61 | std::cout << "OSPRay rank " << mpiRank << "/" << mpiWorldSize << "\n"; |
| 62 | |
| 63 | // load the MPI module, and select the MPI distributed device. Here we |
| 64 | // do not call ospInit, as we want to explicitly pick the distributed |
| 65 | // device |
| 66 | auto OSPRAY_MPI_DISTRIBUTED_GPU = |
| 67 | utility::getEnvVar<int>("OSPRAY_MPI_DISTRIBUTED_GPU").value_or(0); |
| 68 | if (OSPRAY_MPI_DISTRIBUTED_GPU) { |
| 69 | ospLoadModule("mpi_distributed_gpu"); |
| 70 | } else { |
| 71 | ospLoadModule("mpi_distributed_cpu"); |
| 72 | } |
| 73 | |
| 74 | { |
| 75 | cpp::Device mpiDevice("mpiDistributed"); |
| 76 | mpiDevice.commit(); |
| 77 | mpiDevice.setCurrent(); |
| 78 | |
| 79 | // set an error callback to catch any OSPRay errors and exit the application |
| 80 | ospDeviceSetErrorCallback( |
| 81 | mpiDevice.handle(), |
| 82 | [](void *, OSPError error, const char *errorDetails) { |
| 83 | std::cerr << "OSPRay error: " << errorDetails << std::endl; |
| 84 | exit(error); |
| 85 | }, |
| 86 | nullptr); |
| 87 | |
| 88 | // all ranks specify the same rendering parameters, with the exception of |
| 89 | // the data to be rendered, which is distributed among the ranks |
| 90 | VolumeBrick brick = makeLocalVolume(mpiRank, mpiWorldSize); |
| 91 | |
| 92 | // create the "world" model which will contain all of our geometries |
| 93 | cpp::World world; |
| 94 | world.setParam("instance", cpp::CopiedData(brick.instance)); |
| 95 | |
| 96 | world.setParam("region", cpp::CopiedData(brick.bounds)); |
| 97 | world.commit(); |
| 98 | |
| 99 | // create OSPRay renderer |
| 100 | cpp::Renderer renderer("mpiRaycast"); |
| 101 |
nothing calls this directly
no test coverage detected