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