/*@ MPI_Init_thread - Initialize the MPI execution environment Input Parameters: + argc - Pointer to the number of arguments . argv - Pointer to the argument vector - required - Level of desired thread support Output Parameters: . provided - Level of provided thread support Command line arguments: MPI specifies no command-line arguments but does allow an MPI implementation to make use of them. See 'MPI_INIT' for a description of the command line arguments supported by 'MPI_INIT' and 'MPI_INIT_THREAD'. Notes: The valid values for the level of thread support are\: + MPI_THREAD_SINGLE - Only one thread will execute. . MPI_THREAD_FUNNELED - The process may be multi-threaded, but only the main thread will make MPI calls (all MPI calls are funneled to the main thread). . MPI_THREAD_SERIALIZED - The process may be multi-threaded, and multiple threads may make MPI calls, but only one at a time: MPI calls are not made concurrently from two distinct threads (all MPI calls are serialized). - MPI_THREAD_MULTIPLE - Multiple threads may call MPI, with no restrictions. Notes for Fortran: Note that the Fortran binding for this routine does not have the 'argc' and 'argv' arguments. ('MPI_INIT_THREAD(required, provided, ierror)') .N Errors .N MPI_SUCCESS .N MPI_ERR_OTHER .seealso: MPI_Init, MPI_Finalize @*/ int MPI_Init_thread(int *argc, char ***argv, int required, int *provided) { int mpi_errno = MPI_SUCCESS; int rc ATTRIBUTE((unused)), reqd = required; MPIR_FUNC_TERSE_INIT_STATE_DECL(MPID_STATE_MPI_INIT_THREAD); rc = MPID_Wtime_init(); #ifdef MPL_USE_DBG_LOGGING MPL_dbg_pre_init(argc, argv, rc); #endif MPIR_FUNC_TERSE_INIT_ENTER(MPID_STATE_MPI_INIT_THREAD); #ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { if (OPA_load_int(&MPIR_Process.mpich_state) != MPICH_MPI_STATE__PRE_INIT) { mpi_errno = MPIR_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE, "MPI_Init_thread", __LINE__, MPI_ERR_OTHER, "**inittwice", 0); } if (mpi_errno != MPI_SUCCESS) goto fn_fail; } MPID_END_ERROR_CHECKS; } #endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ /* Temporarily disable thread-safety. This is needed because the * mutexes are not initialized yet, and we don't want to * accidentally use them before they are initialized. We will * reset this value once it is properly initialized. */ #if defined MPICH_IS_THREADED MPIR_ThreadInfo.isThreaded = 0; #endif /* MPICH_IS_THREADED */ MPIR_T_env_init(); /* If the user requested for asynchronous progress, request for * THREAD_MULTIPLE. */ if (MPIR_CVAR_ASYNC_PROGRESS) reqd = MPI_THREAD_MULTIPLE; mpi_errno = MPIR_Init_thread(argc, argv, reqd, provided); if (mpi_errno != MPI_SUCCESS) goto fn_fail; if (MPIR_CVAR_ASYNC_PROGRESS) { #if MPL_THREAD_PACKAGE_NAME == MPL_THREAD_PACKAGE_ARGOBOTS printf("WARNING: Asynchronous progress is not supported with Argobots\n"); goto fn_fail; #else if (*provided == MPI_THREAD_MULTIPLE) { mpi_errno = MPID_Init_async_thread(); if (mpi_errno) goto fn_fail; MPIR_async_thread_initialized = 1; } else { printf("WARNING: No MPI_THREAD_MULTIPLE support (needed for async progress)\n"); } #endif } /* ... end of body of routine ... */ MPIR_FUNC_TERSE_INIT_EXIT(MPID_STATE_MPI_INIT_THREAD); return mpi_errno; fn_fail: /* --BEGIN ERROR HANDLING-- */ #ifdef HAVE_ERROR_REPORTING { mpi_errno = MPIR_Err_create_code(mpi_errno, MPIR_ERR_RECOVERABLE, __func__, __LINE__, MPI_ERR_OTHER, "**mpi_init_thread", "**mpi_init_thread %p %p %d %p", argc, argv, required, provided); } #endif mpi_errno = MPIR_Err_return_comm(0, __func__, mpi_errno); MPIR_FUNC_TERSE_INIT_EXIT(MPID_STATE_MPI_INIT_THREAD); MPID_THREAD_CS_EXIT(GLOBAL, MPIR_THREAD_GLOBAL_ALLFUNC_MUTEX); return mpi_errno; /* --END ERROR HANDLING-- */ }
/*@ MPI_Init_thread - Initialize the MPI execution environment Input Parameters: + argc - Pointer to the number of arguments . argv - Pointer to the argument vector - required - Level of desired thread support Output Parameter: . provided - Level of provided thread support Command line arguments: MPI specifies no command-line arguments but does allow an MPI implementation to make use of them. See 'MPI_INIT' for a description of the command line arguments supported by 'MPI_INIT' and 'MPI_INIT_THREAD'. Notes: The valid values for the level of thread support are\: + MPI_THREAD_SINGLE - Only one thread will execute. . MPI_THREAD_FUNNELED - The process may be multi-threaded, but only the main thread will make MPI calls (all MPI calls are funneled to the main thread). . MPI_THREAD_SERIALIZED - The process may be multi-threaded, and multiple threads may make MPI calls, but only one at a time: MPI calls are not made concurrently from two distinct threads (all MPI calls are serialized). - MPI_THREAD_MULTIPLE - Multiple threads may call MPI, with no restrictions. Notes for Fortran: Note that the Fortran binding for this routine does not have the 'argc' and 'argv' arguments. ('MPI_INIT_THREAD(required, provided, ierror)') .N Errors .N MPI_SUCCESS .N MPI_ERR_OTHER .seealso: MPI_Init, MPI_Finalize @*/ int MPI_Init_thread( int *argc, char ***argv, int required, int *provided ) { int mpi_errno = MPI_SUCCESS; int rc, reqd = required; MPID_MPI_INIT_STATE_DECL(MPID_STATE_MPI_INIT_THREAD); rc = MPID_Wtime_init(); #ifdef USE_DBG_LOGGING MPIU_DBG_PreInit( argc, argv, rc ); #endif MPID_MPI_INIT_FUNC_ENTER(MPID_STATE_MPI_INIT_THREAD); #if defined(_OSU_MVAPICH_) || defined(_OSU_PSM_) MV2_Read_env_vars(); #endif /* defined(_OSU_MVAPICH_) || defined(_OSU_PSM_) */ # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { if (MPIR_Process.initialized != MPICH_PRE_INIT) { mpi_errno = MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE, "MPI_Init_thread", __LINE__, MPI_ERR_OTHER, "**inittwice", 0 ); } if (mpi_errno != MPI_SUCCESS) goto fn_fail; } MPID_END_ERROR_CHECKS; } # endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ /* If the user requested for asynchronous progress, request for * THREAD_MULTIPLE. */ rc = 0; MPL_env2bool("MPICH_ASYNC_PROGRESS", &rc); if (rc) reqd = MPI_THREAD_MULTIPLE; mpi_errno = MPIR_Init_thread( argc, argv, reqd, provided ); if (mpi_errno != MPI_SUCCESS) goto fn_fail; if (rc && *provided == MPI_THREAD_MULTIPLE) { mpi_errno = MPIR_Init_async_thread(); if (mpi_errno) goto fn_fail; MPIR_async_thread_initialized = 1; } /* ... end of body of routine ... */ MPID_MPI_INIT_FUNC_EXIT(MPID_STATE_MPI_INIT_THREAD); return mpi_errno; fn_fail: /* --BEGIN ERROR HANDLING-- */ # ifdef HAVE_ERROR_REPORTING { mpi_errno = MPIR_Err_create_code( mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**mpi_init_thread", "**mpi_init_thread %p %p %d %p", argc, argv, required, provided); } # endif mpi_errno = MPIR_Err_return_comm( 0, FCNAME, mpi_errno ); MPID_MPI_INIT_FUNC_EXIT(MPID_STATE_MPI_INIT_THREAD); MPIU_THREAD_CS_EXIT(INIT,*provided); return mpi_errno; /* --END ERROR HANDLING-- */ }
/*@ MPI_Init - Initialize the MPI execution environment Input Parameters: + argc - Pointer to the number of arguments - argv - Pointer to the argument vector Thread and Signal Safety: This routine must be called by one thread only. That thread is called the `main thread` and must be the thread that calls 'MPI_Finalize'. Notes: The MPI standard does not say what a program can do before an 'MPI_INIT' or after an 'MPI_FINALIZE'. In the MPICH implementation, you should do as little as possible. In particular, avoid anything that changes the external state of the program, such as opening files, reading standard input or writing to standard output. Notes for Fortran: The Fortran binding for 'MPI_Init' has only the error return .vb subroutine MPI_INIT( ierr ) integer ierr .ve .N Errors .N MPI_SUCCESS .N MPI_ERR_INIT .seealso: MPI_Init_thread, MPI_Finalize @*/ int MPI_Init( int *argc, char ***argv ) { static const char FCNAME[] = "MPI_Init"; int mpi_errno = MPI_SUCCESS; int rc; int threadLevel, provided; MPID_MPI_INIT_STATE_DECL(MPID_STATE_MPI_INIT); rc = MPID_Wtime_init(); #ifdef USE_DBG_LOGGING MPIU_DBG_PreInit( argc, argv, rc ); #endif MPID_MPI_INIT_FUNC_ENTER(MPID_STATE_MPI_INIT); # ifdef HAVE_ERROR_CHECKING { MPID_BEGIN_ERROR_CHECKS; { if (MPIR_Process.initialized != MPICH_PRE_INIT) { mpi_errno = MPIR_Err_create_code( MPI_SUCCESS, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**inittwice", NULL ); } if (mpi_errno) goto fn_fail; } MPID_END_ERROR_CHECKS; } # endif /* HAVE_ERROR_CHECKING */ /* ... body of routine ... */ #if (MPICH_THREAD_LEVEL == MPI_THREAD_MULTIPLE) /* If we support all thread levels, allow the use of an environment variable to set the default thread level */ { const char *str = 0; threadLevel = MPI_THREAD_SINGLE; if (MPL_env2str( "MPICH_THREADLEVEL_DEFAULT", &str )) { if (strcmp(str,"MULTIPLE") == 0 || strcmp(str,"multiple") == 0) { threadLevel = MPI_THREAD_MULTIPLE; } else if (strcmp(str,"SERIALIZED") == 0 || strcmp(str,"serialized") == 0) { threadLevel = MPI_THREAD_SERIALIZED; } else if (strcmp(str,"FUNNELED") == 0 || strcmp(str,"funneled") == 0) { threadLevel = MPI_THREAD_FUNNELED; } else if (strcmp(str,"SINGLE") == 0 || strcmp(str,"single") == 0) { threadLevel = MPI_THREAD_SINGLE; } else { MPIU_Error_printf( "Unrecognized thread level %s\n", str ); exit(1); } } } #else threadLevel = MPI_THREAD_SINGLE; #endif /* If the user requested for asynchronous progress, request for * THREAD_MULTIPLE. */ rc = 0; MPL_env2bool("MPICH_ASYNC_PROGRESS", &rc); if (rc) threadLevel = MPI_THREAD_MULTIPLE; mpi_errno = MPIR_Init_thread( argc, argv, threadLevel, &provided ); if (mpi_errno != MPI_SUCCESS) goto fn_fail; if (rc && provided == MPI_THREAD_MULTIPLE) { mpi_errno = MPIR_Init_async_thread(); if (mpi_errno) goto fn_fail; MPIR_async_thread_initialized = 1; } /* ... end of body of routine ... */ MPID_MPI_INIT_FUNC_EXIT(MPID_STATE_MPI_INIT); return mpi_errno; fn_fail: /* --BEGIN ERROR HANDLING-- */ # ifdef HAVE_ERROR_REPORTING { mpi_errno = MPIR_Err_create_code( mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, "**mpi_init", "**mpi_init %p %p", argc, argv); } # endif mpi_errno = MPIR_Err_return_comm( 0, FCNAME, mpi_errno ); return mpi_errno; /* --END ERROR HANDLING-- */ }