/// PMlib Fortran インタフェイス /// MPIランク別詳細レポート、HWPC詳細レポートを出力。 非排他測定区間も出力 /// /// @param[in] char* fc 出力ファイル名(character文字列) /// @param[in] legend HWPC 記号説明の表示(0:表示する、1:表示しない) /// @param[in] int psort 測定区間の表示順 /// (0:経過時間順にソート後表示、1:登録順で表示) /// @param[in] int fc_size 出力ファイル名の文字数 /// /// @note Fortranコンパイラはfc_size引数を自動的に追加してしまう /// void f_pm_printdetail_ (char* fc, int& legend, int &psort, int fc_size) { FILE *fp; std::string s=std::string(fc,fc_size); #ifdef DEBUG_FORT fprintf(stderr, "<f_pm_printdetail_> fc=%s, legend=%d, psort=%d, fc_size=%d \n", fc, legend, psort, fc_size); #endif int user_file; if (s == "" || fc_size == 0) { // if filename is null, report to stdout fp=stdout; user_file=0; } else { fp=fopen(fc,"a"); if (fp == NULL) { fprintf(stderr, "*** warning <f_pm_printdetail_> can not open: %s\n", fc); fp=stdout; user_file=0; } else { user_file=1; } } if (psort != 0 && psort != 1) psort = 0; PM.printDetail(fp, legend, psort); if (user_file == 1) { fclose(fp); } return; }
/// PMlib Fortran インタフェイス /// プロセスグループ単位でのMPIランク別詳細レポート、HWPC詳細レポート出力 /// /// @param[in] char* fc ラベルとなる character文字列 /// @param[in] p_group MPI_Group型 groupのgroup handle /// @param[in] p_comm MPI_Comm型 groupに対応するcommunicator /// @param[in] pp_ranks int**型 groupを構成するrank番号配列へのポインタ /// @param[in] group int型 プロセスグループ番号 /// @param[in] legend int型 HWPC 記号説明の表示 (0:表示する、1:表示しない) /// @param[in] int psort 測定区間の表示順 /// (0:経過時間順にソート後表示、1:登録順で表示) /// @param[in] int fc_size character文字列ラベルの長さ(文字数) /// /// @note MPI_Group, MPI_Comm型は呼び出すFortran側では integer 型である /// @note Fortranコンパイラはfc_size引数を自動的に追加してしまう /// void f_pm_printgroup_ (char* fc, MPI_Group p_group, MPI_Comm p_comm, int* pp_ranks, int& group, int& legend, int &psort, int fc_size) { FILE *fp; std::string s=std::string(fc,fc_size); #ifdef DEBUG_FORT fprintf(stderr, "<f_pm_printgroup_> fc=%s, group=%d, legend=%d, psort=%d, fc_size=%d \n", fc, group, legend, psort, fc_size); #endif if (s == "" || fc_size == 0) { // filename is null. PMlib report is merged to stdout fp=stdout; } else { fp=fopen(fc,"w+"); if (fp == NULL) { fprintf(stderr, "*** warning <f_pm_printgroup_> can not open: %s\n", fc); fp=stdout; } } if (psort != 0 && psort != 1) psort = 0; PM.printGroup(fp, p_group, p_comm, pp_ranks, group, legend, psort); return; }
/// PMlib Fortran インタフェイス /// 全プロセスの全測定結果情報をマスタープロセス(0)に集約 /// void f_pm_gather_ (void) { #ifdef DEBUG_FORT fprintf(stderr, "<f_pm_gather_> \n"); #endif PM.gather(); return; }
/// PMlib Fortran インタフェイス /// PMlibの初期化. /// /// @param[in] init_nWatch 最初に確保する測定区間数。 /// /// @note 測定区間数 m_nWatch は不足すると内部で自動的に追加する /// @note Fortran とC++間のインタフェイスでは引数を省略する事はできないため、 /// PMlib C++の引数仕様と異なる事に注意 /// void f_pm_initialize_ (int& init_nWatch) { int num_threads; int num_process; int my_rank; #ifdef DEBUG_FORT fprintf(stderr, "<f_pm_initialize_> init_nWatch=%d\n", init_nWatch); #endif PM.initialize(init_nWatch); #ifdef _PM_WITHOUT_MPI_ #ifdef _OPENMP char parallel_mode[] = "OpenMP"; #else char parallel_mode[] = "Serial"; #endif num_process=1; my_rank=0; #else #ifdef _OPENMP char parallel_mode[] = "Hybrid"; #else char parallel_mode[] = "FlatMPI"; #endif MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); MPI_Comm_size(MPI_COMM_WORLD, &num_process); #endif #ifdef _OPENMP char* c_env = std::getenv("OMP_NUM_THREADS"); if (c_env == NULL) omp_set_num_threads(1); // if not defined, set it as 1 num_threads = omp_get_max_threads(); // PM.num_threads = omp_get_max_threads(); #else num_threads = 1; #endif PM.setRankInfo(my_rank); PM.setParallelMode(parallel_mode, num_threads, num_process); return; }
int main (int argc, char *argv[]) { int my_id, npes, num_threads; int i, j, loop; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &my_id); MPI_Comm_size(MPI_COMM_WORLD, &npes); #ifdef _OPENMP char* c_env = std::getenv("OMP_NUM_THREADS"); if (c_env == NULL) omp_set_num_threads(1); num_threads = omp_get_max_threads(); #else num_threads = 1; #endif PM.initialize(); PM.setProperties("First location", PerfMonitor::CALC); PM.setProperties("Second location", PerfMonitor::CALC); if(my_id == 0) fprintf(stderr, "<main> starting the First location.\n"); set_array(); loop=3; PM.start("First location"); for (i=1; i<=loop; i++){ sub_kernel(); } PM.stop ("First location"); if(my_id == 0) fprintf(stderr, "<main> starting the Second location.\n"); PM.start("Second location"); sub_kernel(); PM.stop ("Second location"); PM.gather(); PM.print(stdout, "", "Mr. Bean"); PM.printDetail(stdout); MPI_Finalize(); return 0; }
/// PMlib Fortran インタフェイス /// 測定区間ストップ /// /// @param[in] label ラベル文字列。測定区間を識別するために用いる。 /// @param[in] fpt 「タスク」あたりの計算量(Flop)または通信量(Byte) /// @param[in] tic 「タスク」実行回数 /// @param[in] int fc_size character文字列ラベルの長さ(文字数) /// /// @note 計算量または通信量をユーザが明示的に指定する場合は、 /// そのボリュームは1区間1回あたりでfpt*ticとして算出される /// @note Fortran PMlib インタフェイスでは引数を省略する事はできない。 /// 引数値 fpt*tic が非0の場合はその数値が採用され、値が0の場合は /// HWPC自動計測値が採用される。 /// @note Fortranコンパイラはfc_size引数を自動的に追加してしまう /// void f_pm_stop_ (char* fc, double& fpt, unsigned& tic, int fc_size) { std::string s=std::string(fc,fc_size); #ifdef DEBUG_FORT fprintf(stderr, "<f_pm_stop_> fc=%s, fpt=%8.0lf, tic=%d, fc_size=%d\n", fc, fpt, tic, fc_size); #endif if (s == "") { fprintf(stderr, "<f_pm_stop_> "); fprintf(stderr, "argument fc is empty(null)\n"); } if (fc_size == 0) { fprintf(stderr, "<f_pm_stop_> "); fprintf(stderr, "argument fc_size is 0\n"); } PM.stop(s, fpt, tic); return; }
/// PMlib Fortran インタフェイス /// 測定区間スタート /// /// @param[in] label ラベル文字列。測定区間を識別するために用いる。 /// @param[in] int fc_size character文字列ラベルの長さ(文字数) /// /// @note Fortranコンパイラはfc_size引数を自動的に追加してしまう /// void f_pm_start_ (char* fc, int fc_size) { std::string s=std::string(fc,fc_size); #ifdef DEBUG_FORT fprintf(stderr, "<f_pm_start_> fc=%s, fc_size=%d\n", fc, fc_size); #endif if (s == "") { fprintf(stderr, "<f_pm_start_> "); fprintf(stderr, "argument fc is empty(null)\n"); } if (fc_size == 0) { fprintf(stderr, "<f_pm_start_> "); fprintf(stderr, "argument fc_size is 0\n"); } PM.start(s); return; }
int main (int argc, char *argv[]) { PM.initialize(); PM.setProperties("Label-1", PerfMonitor::CALC); init2d(); PM.start("Label-1"); mxm2d(); PM.stop ("Label-1"); PM.print(stdout, "", "Mrs. Kobe", 0); PM.printDetail(stdout, 1); printf("something was done^^;\n"); return 0; }
/// PMlib Fortran インタフェイス /// 測定結果の基本統計レポートを出力 /// /// @param[in] char* fc 出力ファイル名(character文字列) /// @param[in] int psort 測定区間の表示順 /// (0:経過時間順にソート後表示、1:登録順で表示) /// @param[in] int fc_size 出力ファイル名の文字数 /// /// @note Fortranコンパイラはfc_size引数を自動的に追加してしまう /// void f_pm_print_ (char* fc, int &psort, int fc_size) { FILE *fp; std::string s=std::string(fc,fc_size); #ifdef DEBUG_FORT fprintf(stderr, "<f_pm_print_> fc=%s, psort=%d, fc_size=%d\n", fc, psort, fc_size); #endif std::string h; std::string u="Fortran API"; char hostname[512]; hostname[0]='\0'; if (gethostname(hostname, sizeof(hostname)) != 0) { fprintf(stderr, "*** warning <f_pm_print_> can not obtain hostname\n"); h="unknown"; } else { h=hostname; } int user_file; if (s == "" || fc_size == 0) { // if filename is null, report to stdout fp=stdout; user_file=0; } else { fp=fopen(fc,"a"); if (fp == NULL) { fprintf(stderr, "*** warning <f_pm_print_> can not open: %s\n", fc); fp=stdout; user_file=0; } else { user_file=1; } } if (psort != 0 && psort != 1) psort = 0; PM.print(fp, h, u, psort); if (user_file == 1) { fclose(fp); } return; }
/// PMlib Fortran インタフェイス /// 測定区間にプロパティを設定. /// /// @param[in] char* fc ラベルとなる character文字列 /// @param[in] int f_type 測定対象タイプ(0:COMM:通信, 1:CALC:計算) /// @param[in] int f_exclusive 排他測定フラグ(0:false, 1:true) /// @param[in] int fc_size character文字列ラベルの長さ(文字数) /// /// @note ラベルは測定区間を識別するために用いる。 /// 各labelに対応したキー番号 key は各ラベル毎に内部で自動生成する /// @note Fortranコンパイラはfc_size引数を自動的に追加してしまう /// void f_pm_setproperties_ (char* fc, int& f_type, int& f_exclusive, int fc_size) { // Note on fortran character 2 C++ string // Although the auto appended fc_size argument value is correct, // fortran character string is not terminated with NUL // A simple conversion such as below is not safe. // std::string s=fc; // So, we do explicit string conversion here... std::string s=std::string(fc,fc_size); bool exclusive; PerfMonitor::Type arg_type; /// 測定対象タイプ from PerfMonitor.h #ifdef DEBUG_FORT fprintf(stderr, "<f_pm_setproperties_> fc=%s, f_type=%d, f_exclusive=%d, fc_size=%d\n", fc, f_type, f_exclusive, fc_size); #endif if (s == "" || fc_size == 0) { fprintf(stderr, "<f_pm_setproperties> argument fc is empty(null)\n"); PM_Exit(0); } if (f_exclusive == 1) { exclusive=true; } else if (f_exclusive == 2) { exclusive=false; } else { fprintf(stderr, "<f_pm_setproperties> "); fprintf(stderr, "argument f_exclusive is invalid: %u\n", f_exclusive); PM_Exit(0); } // PM.setProperties(s, f_type, exclusive); if (f_type == 0) { arg_type = PM.COMM; } else if (f_type == 1) { arg_type = PM.CALC; } else { fprintf(stderr, "<f_pm_setproperties> "); fprintf(stderr, "argument f_type is invalid: %u\n", f_type); PM_Exit(0); } PM.setProperties(s, arg_type, exclusive); return; }
int main (int argc, char *argv[]) { int my_id, num_process, num_threads; int i, j, loop; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &my_id); MPI_Comm_size(MPI_COMM_WORLD, &num_process); MPI_Group my_group; MPI_Comm_group(MPI_COMM_WORLD, &my_group); #ifdef _OPENMP char* c_env = std::getenv("OMP_NUM_THREADS"); if (c_env == NULL) { fprintf (stderr, "undefined OMP_NUM_THREADS is now set as 1\n"); omp_set_num_threads(1); } num_threads = omp_get_max_threads(); #else num_threads = 1; #endif PM.initialize(); PM.setProperties("1st section", PerfMonitor::CALC); PM.setProperties("2nd section", PerfMonitor::CALC); if(my_id == 0) { fprintf(stderr, "<main> starting the WORLD (default) communicator.\n"); } // Create some groups for testing. MPI_Group new_group1, new_group2; MPI_Comm new_comm1, new_comm2; int i_group1, i_group2; int new_size1, new_size2; int *p1_my_id, *p2_my_id; // 1st group new_size1 = std::max(1,num_process/2); p1_my_id = new int[new_size1]; for (i=0; i<new_size1; i++) { p1_my_id[i] = i; } MPI_Group_incl(my_group, new_size1, p1_my_id, &new_group1); MPI_Comm_create(MPI_COMM_WORLD, new_group1, &new_comm1); // 2nd group new_size2 = num_process - new_size1; p2_my_id = new int[new_size2]; for (i=0; i<new_size2; i++) { p2_my_id[i] = new_size1 + i; } MPI_Group_incl(my_group, new_size2, p2_my_id, &new_group2); MPI_Comm_create(MPI_COMM_WORLD, new_group2, &new_comm2); set_array(); // using the world communicator (default) loop=1; PM.start("1st section"); for (i=1; i<=loop; i++){ sub_kernel(); } PM.stop ("1st section"); // using the group communicators PM.start("2nd section"); if(my_id<new_size1) { stream_copy(); } else if(my_id<new_size1+new_size2) { stream_triad(); } else { ; } PM.stop ("2nd section"); PM.gather(); PM.print(stdout, "", "Mr. Bean"); PM.printDetail(stdout); PM.printGroup(stdout, new_group1, new_comm1, p1_my_id, 1); PM.printGroup(stdout, new_group2, new_comm2, p2_my_id, 2, 1); MPI_Finalize(); return 0; }
int main (int argc, char *argv[]) { int my_id, num_process, num_threads; int i, j, k, loop; double flop_count, bandwidth_count, dsize; double t1, t2; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &my_id); MPI_Comm_size(MPI_COMM_WORLD, &num_process); #ifdef _OPENMP char* c_env = std::getenv("OMP_NUM_THREADS"); if (c_env == NULL) { fprintf (stderr, "undefined OMP_NUM_THREADS is now set as 1\n"); omp_set_num_threads(1); } num_threads = omp_get_max_threads(); #else num_threads = 1; #endif PM.initialize(); PM.setProperties("section-1", PerfMonitor::CALC); PM.setProperties("section-2", PerfMonitor::CALC); MPI_Comm new_comm; int icolor, key; int ncolors = 2; icolor = my_id*ncolors / num_process; if(my_id == 0) { fprintf(stderr, "testing MPI_Comm_split. ncolors=%d\n", ncolors); } key = my_id; MPI_Comm_split(MPI_COMM_WORLD, icolor, key, &new_comm); // int id, size; // MPI_Comm_rank(new_comm, &id); // new rank id within new_comm // MPI_Comm_size(new_comm, &size); // the size of new_comm // fprintf(stderr, "\t my_id=%d, icolor=%d, id=%d\n", my_id,icolor,id); PM.start("section-1"); set_array(); PM.stop ("section-1"); // sub_kernel(); PM.start("section-2"); if(icolor == 1) { stream_copy(); } else { stream_triad(); } PM.stop ("section-2"); PM.gather(); PM.print(stdout, "", ""); PM.printDetail(stdout); PM.printComm (stdout, new_comm, icolor, key); // PM.print(stdout, "", "", 1); // PM.printDetail(stdout, 0, 1); // PM.printComm (stdout, new_comm, icolor, key, 0, 1); MPI_Finalize(); return 0; }