setparams.c 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175
  1. //
  2. // Copyright 2010 Intel Corporation
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. //
  16. /*
  17. * This utility configures a NPB to be built for a specific number
  18. * of nodes and a specific class. It creates a file "npbparams.h"
  19. * in the source directory. This file keeps state information about
  20. * which size of benchmark is currently being built (so that nothing
  21. * if unnecessarily rebuilt) and defines (through PARAMETER statements)
  22. * the number of nodes and class for which a benchmark is being built.
  23. * The utility takes 3 arguments:
  24. * setparams benchmark-name nprocs class
  25. * benchmark-name is "sp", "bt", etc
  26. * nprocs is the number of processors to run on
  27. * class is the size of the benchmark
  28. * These parameters are checked for the current benchmark. If they
  29. * are invalid, this program prints a message and aborts.
  30. * If the parameters are ok, the current npbsize.h (actually just
  31. * the first line) is read in. If the new parameters are the same as
  32. * the old, nothing is done, but an exit code is returned to force the
  33. * user to specify (otherwise the make procedure succeeds but builds a
  34. * binary of the wrong name). Otherwise the file is rewritten.
  35. * Errors write a message (to stdout) and abort.
  36. *
  37. * This program makes use of two extra benchmark "classes"
  38. * class "X" means an invalid specification. It is returned if
  39. * there is an error parsing the config file.
  40. * class "U" is an external specification meaning "unknown class"
  41. *
  42. * Unfortunately everything has to be case sensitive. This is
  43. * because we can always convert lower to upper or v.v. but
  44. * can't feed this information back to the makefile, so typing
  45. * make CLASS=a and make CLASS=A will produce different binaries.
  46. *
  47. *
  48. */
  49. #include <sys/types.h>
  50. #include <stdlib.h>
  51. #include <stdio.h>
  52. #include <ctype.h>
  53. #include <string.h>
  54. #include <time.h>
  55. /*
  56. * This is the master version number for this set of
  57. * NPB benchmarks. It is in an obscure place so people
  58. * won't accidentally change it.
  59. */
  60. #define VERSION "3.3"
  61. /* controls verbose output from setparams */
  62. /* #define VERBOSE */
  63. #define FILENAME "npbparams.h"
  64. #define DESC_LINE "c NPROCS = %d CLASS = %c\n"
  65. #define C_DESC_LINE "// NPROCS = %d CLASS = %c\n"
  66. #define BT_DESC_LINE "// NPROCS = %d CLASS = %c SUBTYPE = %s\n"
  67. #define DEF_CLASS_LINE "#define CLASS '%c'\n"
  68. #define DEF_NUM_PROCS_LINE "#define NUM_PROCS %d\n"
  69. #define FINDENT " "
  70. #define CONTINUE " > "
  71. #ifdef FORTRAN_REC_SIZE
  72. int fortran_rec_size = FORTRAN_REC_SIZE;
  73. #else
  74. int fortran_rec_size = 4;
  75. #endif
  76. void get_info(int argc, char *argv[], int *typep, int *nprocsp, char *classp,
  77. int* subtypep);
  78. void check_info(int type, int nprocs, char class);
  79. void read_info(int type, int *nprocsp, char *classp, int *subtypep);
  80. void write_info(int type, int nprocs, char class, int subtype);
  81. void write_sp_info(FILE *fp, int nprocs, char class);
  82. void write_bt_info(FILE *fp, int nprocs, char class, int io);
  83. void write_lu_info(FILE *fp, int nprocs, char class);
  84. void write_mg_info(FILE *fp, int nprocs, char class);
  85. void write_cg_info(FILE *fp, int nprocs, char class);
  86. void write_ft_info(FILE *fp, int nprocs, char class);
  87. void write_ep_info(FILE *fp, int nprocs, char class);
  88. void write_is_info(FILE *fp, int nprocs, char class);
  89. void write_dt_info(FILE *fp, int nprocs, char class);
  90. void write_compiler_info(int type, FILE *fp);
  91. void write_convertdouble_info(int type, FILE *fp);
  92. void check_line(char *line, char *label, char *val);
  93. int check_include_line(char *line, char *filename);
  94. void put_string(FILE *fp, char *name, char *val);
  95. void put_def_string(FILE *fp, char *name, char *val);
  96. void put_def_variable(FILE *fp, char *name, char *val);
  97. int isqrt(int i);
  98. int ilog2(int i);
  99. int ipow2(int i);
  100. enum benchmark_types {SP, BT, LU, MG, FT, IS, DT, EP, CG};
  101. enum iotypes { NONE = 0, FULL, SIMPLE, EPIO, FORTRAN};
  102. int main(int argc, char *argv[])
  103. {
  104. int nprocs, nprocs_old, type;
  105. char class, class_old;
  106. int subtype = -1, old_subtype = -1;
  107. /* Get command line arguments. Make sure they're ok. */
  108. get_info(argc, argv, &type, &nprocs, &class, &subtype);
  109. if (class != 'U') {
  110. #ifdef VERBOSE
  111. printf("setparams: For benchmark %s: number of processors = %d class = %c\n",
  112. argv[1], nprocs, class);
  113. #endif
  114. check_info(type, nprocs, class);
  115. }
  116. /* Get old information. */
  117. read_info(type, &nprocs_old, &class_old, &old_subtype);
  118. if (class != 'U') {
  119. if (class_old != 'X') {
  120. #ifdef VERBOSE
  121. printf("setparams: old settings: number of processors = %d class = %c\n",
  122. nprocs_old, class_old);
  123. #endif
  124. }
  125. } else {
  126. printf("setparams:\n\
  127. *********************************************************************\n\
  128. * You must specify NPROCS and CLASS to build this benchmark *\n\
  129. * For example, to build a class A benchmark for 4 processors, type *\n\
  130. * make {benchmark-name} NPROCS=4 CLASS=A *\n\
  131. *********************************************************************\n\n");
  132. if (class_old != 'X') {
  133. #ifdef VERBOSE
  134. printf("setparams: Previous settings were CLASS=%c NPROCS=%d\n",
  135. class_old, nprocs_old);
  136. #endif
  137. }
  138. exit(1); /* exit on class==U */
  139. }
  140. /* Write out new information if it's different. */
  141. if (nprocs != nprocs_old || class != class_old || subtype != old_subtype) {
  142. #ifdef VERBOSE
  143. printf("setparams: Writing %s\n", FILENAME);
  144. #endif
  145. write_info(type, nprocs, class, subtype);
  146. } else {
  147. #ifdef VERBOSE
  148. printf("setparams: Settings unchanged. %s unmodified\n", FILENAME);
  149. #endif
  150. }
  151. return 0;
  152. }
  153. /*
  154. * get_info(): Get parameters from command line
  155. */
  156. void get_info(int argc, char *argv[], int *typep, int *nprocsp, char *classp,
  157. int *subtypep)
  158. {
  159. if (argc < 4) {
  160. printf("Usage: %s (%d) benchmark-name nprocs class\n", argv[0], argc);
  161. exit(1);
  162. }
  163. *nprocsp = atoi(argv[2]);
  164. *classp = *argv[3];
  165. if (!strcmp(argv[1], "sp") || !strcmp(argv[1], "SP")) *typep = SP;
  166. else if (!strcmp(argv[1], "ft") || !strcmp(argv[1], "FT")) *typep = FT;
  167. else if (!strcmp(argv[1], "lu") || !strcmp(argv[1], "LU")) *typep = LU;
  168. else if (!strcmp(argv[1], "mg") || !strcmp(argv[1], "MG")) *typep = MG;
  169. else if (!strcmp(argv[1], "is") || !strcmp(argv[1], "IS")) *typep = IS;
  170. else if (!strcmp(argv[1], "dt") || !strcmp(argv[1], "DT")) *typep = DT;
  171. else if (!strcmp(argv[1], "ep") || !strcmp(argv[1], "EP")) *typep = EP;
  172. else if (!strcmp(argv[1], "cg") || !strcmp(argv[1], "CG")) *typep = CG;
  173. else if (!strcmp(argv[1], "bt") || !strcmp(argv[1], "BT")) {
  174. *typep = BT;
  175. if (argc != 5) {
  176. /* printf("Usage: %s (%d) benchmark-name nprocs class\n", argv[0], argc); */
  177. /* exit(1); */
  178. *subtypep = NONE;
  179. } else {
  180. if (!strcmp(argv[4], "full") || !strcmp(argv[4], "FULL")) {
  181. *subtypep = FULL;
  182. } else if (!strcmp(argv[4], "simple") || !strcmp(argv[4], "SIMPLE")) {
  183. *subtypep = SIMPLE;
  184. } else if (!strcmp(argv[4], "epio") || !strcmp(argv[4], "EPIO")) {
  185. *subtypep = EPIO;
  186. } else if (!strcmp(argv[4], "fortran") || !strcmp(argv[4], "FORTRAN")) {
  187. *subtypep = FORTRAN;
  188. } else if (!strcmp(argv[4], "none") || !strcmp(argv[4], "NONE")) {
  189. *subtypep = NONE;
  190. } else {
  191. printf("setparams: Error: unknown btio type %s\n", argv[4]);
  192. exit(1);
  193. }
  194. }
  195. } else {
  196. printf("setparams: Error: unknown benchmark type %s\n", argv[1]);
  197. exit(1);
  198. }
  199. }
  200. /*
  201. * check_info(): Make sure command line data is ok for this benchmark
  202. */
  203. void check_info(int type, int nprocs, char class)
  204. {
  205. int rootprocs, logprocs;
  206. /* check number of processors */
  207. if (nprocs <= 0) {
  208. printf("setparams: Number of processors must be greater than zero\n");
  209. exit(1);
  210. }
  211. switch(type) {
  212. case SP:
  213. case BT:
  214. rootprocs = isqrt(nprocs);
  215. if (rootprocs < 0) {
  216. printf("setparams: Number of processors %d must be a square (1,4,9,...) for this benchmark",
  217. nprocs);
  218. exit(1);
  219. }
  220. if (class == 'S' && nprocs > 16) {
  221. printf("setparams: BT and SP sample sizes cannot be run on more\n");
  222. printf(" than 16 processors because the cell size would be too small.\n");
  223. exit(1);
  224. }
  225. break;
  226. case CG:
  227. case FT:
  228. case MG:
  229. case IS:
  230. case LU:
  231. logprocs = ilog2(nprocs);
  232. if (logprocs < 0) {
  233. printf("setparams: Number of processors must be a power of two (1,2,4,...) for this benchmark\n");
  234. exit(1);
  235. }
  236. break;
  237. case EP:
  238. case DT:
  239. break;
  240. default:
  241. /* never should have gotten this far with a bad name */
  242. printf("setparams: (Internal Error) Benchmark type %d unknown to this program\n", type);
  243. exit(1);
  244. }
  245. /* check class */
  246. if (class != 'S' &&
  247. class != 'W' &&
  248. class != 'A' &&
  249. class != 'B' &&
  250. class != 'C' &&
  251. class != 'D' &&
  252. class != 'E') {
  253. printf("setparams: Unknown benchmark class %c\n", class);
  254. printf("setparams: Allowed classes are \"S\", \"W\", and \"A\" through \"E\"\n");
  255. exit(1);
  256. }
  257. if (class == 'E' && (type == IS || type == DT)) {
  258. printf("setparams: Benchmark class %c not defined for IS or DT\n", class);
  259. exit(1);
  260. }
  261. if (class == 'D' && type == IS && nprocs < 4) {
  262. printf("setparams: IS class D size cannot be run on less than 4 processors\n");
  263. exit(1);
  264. }
  265. }
  266. /*
  267. * read_info(): Read previous information from file.
  268. * Not an error if file doesn't exist, because this
  269. * may be the first time we're running.
  270. * Assumes the first line of the file is in a special
  271. * format that we understand (since we wrote it).
  272. */
  273. void read_info(int type, int *nprocsp, char *classp, int *subtypep)
  274. {
  275. int nread = 0;
  276. FILE *fp;
  277. fp = fopen(FILENAME, "r");
  278. if (fp == NULL) {
  279. #ifdef VERBOSE
  280. printf("setparams: INFO: configuration file %s does not exist (yet)\n", FILENAME);
  281. #endif
  282. goto abort;
  283. }
  284. /* first line of file contains info (fortran), first two lines (C) */
  285. switch(type) {
  286. case BT: {
  287. char subtype_str[100];
  288. nread = fscanf(fp, BT_DESC_LINE, nprocsp, classp, subtype_str);
  289. if (nread != 3) {
  290. if (nread != 2) {
  291. printf("setparams: Error parsing config file %s. Ignoring previous settings\n", FILENAME);
  292. goto abort;
  293. }
  294. *subtypep = 0;
  295. break;
  296. }
  297. if (!strcmp(subtype_str, "full") || !strcmp(subtype_str, "FULL")) {
  298. *subtypep = FULL;
  299. } else if (!strcmp(subtype_str, "simple") ||
  300. !strcmp(subtype_str, "SIMPLE")) {
  301. *subtypep = SIMPLE;
  302. } else if (!strcmp(subtype_str, "epio") || !strcmp(subtype_str, "EPIO")) {
  303. *subtypep = EPIO;
  304. } else if (!strcmp(subtype_str, "fortran") ||
  305. !strcmp(subtype_str, "FORTRAN")) {
  306. *subtypep = FORTRAN;
  307. } else {
  308. *subtypep = -1;
  309. }
  310. break;
  311. }
  312. case SP:
  313. case FT:
  314. case MG:
  315. case LU:
  316. case EP:
  317. case CG:
  318. nread = fscanf(fp, C_DESC_LINE, nprocsp, classp);
  319. if (nread != 2) {
  320. printf("setparams: Error parsing config file %s. Ignoring previous settings\n", FILENAME);
  321. goto abort;
  322. }
  323. break;
  324. case IS:
  325. case DT:
  326. nread = fscanf(fp, DEF_CLASS_LINE, classp);
  327. nread += fscanf(fp, DEF_NUM_PROCS_LINE, nprocsp);
  328. if (nread != 2) {
  329. printf("setparams: Error parsing config file %s. Ignoring previous settings\n", FILENAME);
  330. goto abort;
  331. }
  332. break;
  333. default:
  334. /* never should have gotten this far with a bad name */
  335. printf("setparams: (Internal Error) Benchmark type %d unknown to this program\n", type);
  336. exit(1);
  337. }
  338. fclose(fp);
  339. return;
  340. abort:
  341. *nprocsp = -1;
  342. *classp = 'X';
  343. *subtypep = -1;
  344. return;
  345. }
  346. /*
  347. * write_info(): Write new information to config file.
  348. * First line is in a special format so we can read
  349. * it in again. Then comes a warning. The rest is all
  350. * specific to a particular benchmark.
  351. */
  352. void write_info(int type, int nprocs, char class, int subtype)
  353. {
  354. FILE *fp;
  355. char *BT_TYPES[] = {"NONE", "FULL", "SIMPLE", "EPIO", "FORTRAN"};
  356. fp = fopen(FILENAME, "w");
  357. if (fp == NULL) {
  358. printf("setparams: Can't open file %s for writing\n", FILENAME);
  359. exit(1);
  360. }
  361. switch(type) {
  362. case BT:
  363. /* Write out the header */
  364. if (subtype == -1 || subtype == 0) {
  365. fprintf(fp, C_DESC_LINE, nprocs, class);
  366. } else {
  367. fprintf(fp, BT_DESC_LINE, nprocs, class, BT_TYPES[subtype]);
  368. }
  369. /* Print out a warning so bozos don't mess with the file */
  370. fprintf(fp, "\
  371. // \n\
  372. // \n\
  373. // This file is generated automatically by the setparams utility.\n\
  374. // It sets the number of processors and the class of the NPB\n\
  375. // in this directory. Do not modify it by hand.\n\
  376. // \n");
  377. break;
  378. case SP:
  379. case FT:
  380. case MG:
  381. case LU:
  382. case EP:
  383. case CG:
  384. fprintf(fp, C_DESC_LINE, nprocs, class);
  385. fprintf(fp, "\
  386. // \n\
  387. // \n\
  388. // This file is generated automatically by the setparams utility.\n\
  389. // It sets the number of processors and the class of the NPB\n\
  390. // in this directory. Do not modify it by hand.\n\
  391. // \n");
  392. break;
  393. case IS:
  394. case DT:
  395. fprintf(fp, DEF_CLASS_LINE, class);
  396. fprintf(fp, DEF_NUM_PROCS_LINE, nprocs);
  397. fprintf(fp, "\
  398. /*\n\
  399. This file is generated automatically by the setparams utility.\n\
  400. It sets the number of processors and the class of the NPB\n\
  401. in this directory. Do not modify it by hand. */\n\
  402. \n");
  403. break;
  404. default:
  405. printf("setparams: (Internal error): Unknown benchmark type %d\n",
  406. type);
  407. exit(1);
  408. }
  409. /* Now do benchmark-specific stuff */
  410. switch(type) {
  411. case SP:
  412. write_sp_info(fp, nprocs, class);
  413. break;
  414. case LU:
  415. write_lu_info(fp, nprocs, class);
  416. break;
  417. case MG:
  418. write_mg_info(fp, nprocs, class);
  419. break;
  420. case IS:
  421. write_is_info(fp, nprocs, class);
  422. break;
  423. case DT:
  424. write_dt_info(fp, nprocs, class);
  425. break;
  426. case FT:
  427. write_ft_info(fp, nprocs, class);
  428. break;
  429. case EP:
  430. write_ep_info(fp, nprocs, class);
  431. break;
  432. case CG:
  433. write_cg_info(fp, nprocs, class);
  434. break;
  435. case BT:
  436. write_bt_info(fp, nprocs, class, subtype);
  437. break;
  438. default:
  439. printf("setparams: (Internal error): Unknown benchmark type %d\n", type);
  440. exit(1);
  441. }
  442. write_convertdouble_info(type, fp);
  443. write_compiler_info(type, fp);
  444. fclose(fp);
  445. return;
  446. }
  447. /*
  448. * write_sp_info(): Write SP specific info to config file
  449. */
  450. void write_sp_info(FILE *fp, int nprocs, char class)
  451. {
  452. int maxcells, problem_size, niter;
  453. char *dt;
  454. maxcells = isqrt(nprocs);
  455. if (class == 'S') { problem_size = 12; dt = "0.015e0"; niter = 100; }
  456. else if (class == 'W') { problem_size = 36; dt = "0.0015e0"; niter = 400; }
  457. else if (class == 'A') { problem_size = 64; dt = "0.0015e0"; niter = 400; }
  458. else if (class == 'B') { problem_size = 102; dt = "0.001e0"; niter = 400; }
  459. else if (class == 'C') { problem_size = 162; dt = "0.00067e0"; niter = 400; }
  460. else if (class == 'D') { problem_size = 408; dt = "0.00030e0"; niter = 500; }
  461. else if (class == 'E') { problem_size = 1020; dt = "0.0001e0"; niter = 500; }
  462. else {
  463. printf("setparams: Internal error: invalid class %c\n", class);
  464. exit(1);
  465. }
  466. fprintf(fp, "#define MAXCELLS %d\n",
  467. maxcells);
  468. fprintf(fp, "#define PROBLEM_SIZE %d\n",
  469. problem_size);
  470. fprintf(fp, "#define NITER_DEFAULT %d\n",
  471. niter);
  472. fprintf(fp, "\nstatic double dt_default = %s;\n\n", dt);
  473. }
  474. /*
  475. * write_bt_info(): Write BT specific info to config file
  476. */
  477. void write_bt_info(FILE *fp, int nprocs, char class, int io)
  478. {
  479. int maxcells, problem_size, niter, wr_interval;
  480. char *dt;
  481. maxcells = isqrt(nprocs);
  482. if (class == 'S') { problem_size = 12; dt = "0.010e0"; niter = 60; }
  483. else if (class == 'W') { problem_size = 24; dt = "0.0008e0"; niter = 200; }
  484. else if (class == 'A') { problem_size = 64; dt = "0.0008e0"; niter = 200; }
  485. else if (class == 'B') { problem_size = 102; dt = "0.0003e0"; niter = 200; }
  486. else if (class == 'C') { problem_size = 162; dt = "0.0001e0"; niter = 200; }
  487. else if (class == 'D') { problem_size = 408; dt = "0.00002e0"; niter = 250; }
  488. else if (class == 'E') { problem_size = 1020; dt = "0.4e-5"; niter = 250; }
  489. else {
  490. printf("setparams: Internal error: invalid class %c\n", class);
  491. exit(1);
  492. }
  493. wr_interval = 5;
  494. fprintf(fp, "#define MAXCELLS %d\n",
  495. maxcells);
  496. fprintf(fp, "#define PROBLEM_SIZE %d\n",
  497. problem_size);
  498. fprintf(fp, "#define NITER_DEFAULT %d\n",
  499. niter);
  500. if (io)
  501. fprintf(fp, "#define BTIO_SUBTYPE %d\n", io);
  502. fprintf(fp, "\n");
  503. fprintf(fp, "static double dt_default = %s;\n", dt);
  504. fprintf(fp, "static int wr_default = %d;\n", wr_interval);
  505. fprintf(fp, "static int iotype = %d;\n", io);
  506. if (io) {
  507. switch (io) {
  508. case FULL:
  509. fprintf(fp, "static char *filenm = \"btio.full.out\";\n");
  510. break;
  511. case SIMPLE:
  512. fprintf(fp, "static char *filenm = \"btio.simple.out\";\n");
  513. break;
  514. case EPIO:
  515. fprintf(fp, "static char *filenm = \"btio.epio.out\";\n");
  516. break;
  517. case FORTRAN:
  518. fprintf(fp, "static char *filenm = \"btio.fortran.out\";\n");
  519. break;
  520. default:
  521. break;
  522. }
  523. }
  524. fprintf(fp, "\n");
  525. }
  526. /*
  527. * write_lu_info(): Write SP specific info to config file
  528. */
  529. void write_lu_info(FILE *fp, int nprocs, char class)
  530. {
  531. int isiz1, isiz2, itmax, inorm, problem_size;
  532. int xdiv, ydiv; /* number of cells in x and y direction */
  533. char *dt_default;
  534. if (class == 'S') { problem_size = 12; dt_default = "0.5e0"; itmax = 50; }
  535. else if (class == 'W') { problem_size = 33; dt_default = "1.5e-3"; itmax = 300; }
  536. else if (class == 'A') { problem_size = 64; dt_default = "2.0e0"; itmax = 250; }
  537. else if (class == 'B') { problem_size = 102; dt_default = "2.0e0"; itmax = 250; }
  538. else if (class == 'C') { problem_size = 162; dt_default = "2.0e0"; itmax = 250; }
  539. else if (class == 'D') { problem_size = 408; dt_default = "1.0e0"; itmax = 300; }
  540. else if (class == 'E') { problem_size = 1020; dt_default = "0.5e0"; itmax = 300; }
  541. else {
  542. printf("setparams: Internal error: invalid class %c\n", class);
  543. exit(1);
  544. }
  545. inorm = itmax;
  546. xdiv = ydiv = ilog2(nprocs)/2;
  547. if (xdiv+ydiv != ilog2(nprocs)) xdiv += 1;
  548. xdiv = ipow2(xdiv); ydiv = ipow2(ydiv);
  549. isiz1 = problem_size/xdiv; if (isiz1*xdiv < problem_size) isiz1++;
  550. isiz2 = problem_size/ydiv; if (isiz2*ydiv < problem_size) isiz2++;
  551. fprintf(fp, "\n// number of nodes for which this version is compiled\n");
  552. fprintf(fp, "%sstatic int nnodes_compiled = %d;\n", FINDENT, nprocs);
  553. fprintf(fp, "\n// full problem size\n");
  554. fprintf(fp, "%sstatic const int isiz01 = %d, isiz02 = %d, isiz03 = %d;\n", FINDENT,
  555. problem_size, problem_size, problem_size);
  556. fprintf(fp, "\n// sub-domain array size\n");
  557. fprintf(fp, "%sstatic const int isiz1 = %d, isiz2 = %d, isiz3 = %d;\n", FINDENT,
  558. isiz1, isiz2, problem_size);
  559. fprintf(fp, "\n// number of iterations and how often to print the norm\n");
  560. fprintf(fp, "%sstatic int itmax_default = %d, inorm_default = %d;\n", FINDENT,
  561. itmax, inorm);
  562. fprintf(fp, "%sstatic double dt_default = %s;\n", FINDENT, dt_default);
  563. }
  564. /*
  565. * write_mg_info(): Write MG specific info to config file
  566. */
  567. void write_mg_info(FILE *fp, int nprocs, char class)
  568. {
  569. int problem_size, nit, log2_size, log2_nprocs, lt_default, lm;
  570. int ndim1, ndim2, ndim3;
  571. if (class == 'S') { problem_size = 32; nit = 4; }
  572. else if (class == 'W') { problem_size = 128; nit = 4; }
  573. else if (class == 'A') { problem_size = 256; nit = 4; }
  574. else if (class == 'B') { problem_size = 256; nit = 20; }
  575. else if (class == 'C') { problem_size = 512; nit = 20; }
  576. else if (class == 'D') { problem_size = 1024; nit = 50; }
  577. else if (class == 'E') { problem_size = 2048; nit = 50; }
  578. else {
  579. printf("setparams: Internal error: invalid class type %c\n", class);
  580. exit(1);
  581. }
  582. log2_size = ilog2(problem_size);
  583. log2_nprocs = ilog2(nprocs);
  584. /* lt is log of largest total dimension */
  585. lt_default = log2_size;
  586. /* log of log of maximum dimension on a node */
  587. lm = log2_size - log2_nprocs/3;
  588. ndim1 = lm;
  589. ndim3 = log2_size - (log2_nprocs+2)/3;
  590. ndim2 = log2_size - (log2_nprocs+1)/3;
  591. fprintf(fp, "static int nprocs_compiled = %d;\n", nprocs);
  592. fprintf(fp, "static int nx_default = %d;\n", problem_size);
  593. fprintf(fp, "static int ny_default = %d;\n", problem_size);
  594. fprintf(fp, "static int nz_default = %d;\n", problem_size);
  595. fprintf(fp, "static int nit_default = %d;\n", nit);
  596. fprintf(fp, "static int debug_default = %d;\n", 0);
  597. fprintf(fp, "#define LM %d\n", lm);
  598. fprintf(fp, "#define LT_DEFAULT %d\n", lt_default);
  599. fprintf(fp, "#define NDIM1 %d\n", ndim1);
  600. fprintf(fp, "#define NDIM2 %d\n", ndim2);
  601. fprintf(fp, "#define NDIM3 %d\n", ndim3);
  602. }
  603. /*
  604. * write_dt_info(): Write DT specific info to config file
  605. */
  606. void write_dt_info(FILE *fp, int nprocs, char class)
  607. {
  608. int num_samples,deviation,num_sources;
  609. if (class == 'S') { num_samples=1728; deviation=128; num_sources=4; }
  610. else if (class == 'W') { num_samples=1728*8; deviation=128*2; num_sources=4*2; }
  611. else if (class == 'A') { num_samples=1728*64; deviation=128*4; num_sources=4*4; }
  612. else if (class == 'B') { num_samples=1728*512; deviation=128*8; num_sources=4*8; }
  613. else if (class == 'C') { num_samples=1728*4096; deviation=128*16; num_sources=4*16; }
  614. else if (class == 'D') { num_samples=1728*4096*8; deviation=128*32; num_sources=4*32; }
  615. else {
  616. printf("setparams: Internal error: invalid class type %c\n", class);
  617. exit(1);
  618. }
  619. fprintf(fp, "#define NUM_SAMPLES %d\n", num_samples);
  620. fprintf(fp, "#define STD_DEVIATION %d\n", deviation);
  621. fprintf(fp, "#define NUM_SOURCES %d\n", num_sources);
  622. }
  623. /*
  624. * write_is_info(): Write IS specific info to config file
  625. */
  626. void write_is_info(FILE *fp, int nprocs, char class)
  627. {
  628. if( class != 'S' &&
  629. class != 'W' &&
  630. class != 'A' &&
  631. class != 'B' &&
  632. class != 'C' &&
  633. class != 'D' )
  634. {
  635. printf("setparams: Internal error: invalid class type %c\n", class);
  636. exit(1);
  637. }
  638. }
  639. /*
  640. * write_cg_info(): Write CG specific info to config file
  641. */
  642. void write_cg_info(FILE *fp, int nprocs, char class)
  643. {
  644. int na,nonzer,niter;
  645. char *shift,*rcond="1.0e-1";
  646. char *shiftS="10.",
  647. *shiftW="12.",
  648. *shiftA="20.",
  649. *shiftB="60.",
  650. *shiftC="110.",
  651. *shiftD="500.",
  652. *shiftE="1.5e3";
  653. int num_proc_cols, num_proc_rows;
  654. if( class == 'S' )
  655. { na=1400; nonzer=7; niter=15; shift=shiftS; }
  656. else if( class == 'W' )
  657. { na=7000; nonzer=8; niter=15; shift=shiftW; }
  658. else if( class == 'A' )
  659. { na=14000; nonzer=11; niter=15; shift=shiftA; }
  660. else if( class == 'B' )
  661. { na=75000; nonzer=13; niter=75; shift=shiftB; }
  662. else if( class == 'C' )
  663. { na=150000; nonzer=15; niter=75; shift=shiftC; }
  664. else if( class == 'D' )
  665. { na=1500000; nonzer=21; niter=100; shift=shiftD; }
  666. else if( class == 'E' )
  667. { na=9000000; nonzer=26; niter=100; shift=shiftE; }
  668. else
  669. {
  670. printf("setparams: Internal error: invalid class type %c\n", class);
  671. exit(1);
  672. }
  673. fprintf( fp, "#define na %d\n", na );
  674. fprintf( fp, "#define nonzer %d\n", nonzer );
  675. fprintf( fp, "static int niter = %d;\n", niter );
  676. fprintf( fp, "static double shift = %s,\n", shift );
  677. fprintf( fp, " rcond = %s;\n", rcond );
  678. num_proc_cols = num_proc_rows = ilog2(nprocs)/2;
  679. if (num_proc_cols+num_proc_rows != ilog2(nprocs)) num_proc_cols += 1;
  680. num_proc_cols = ipow2(num_proc_cols); num_proc_rows = ipow2(num_proc_rows);
  681. fprintf( fp, "\n// number of nodes for which this version is compiled\n" );
  682. fprintf( fp, "static int nnodes_compiled = %d;\n", nprocs );
  683. fprintf( fp, "#define num_proc_cols %d\n", num_proc_cols );
  684. fprintf( fp, "#define num_proc_rows %d\n", num_proc_rows );
  685. }
  686. /*
  687. * write_ft_info(): Write FT specific info to config file
  688. */
  689. void write_ft_info(FILE *fp, int nprocs, char class)
  690. {
  691. /* easiest way (given the way the benchmark is written)
  692. * is to specify log of number of grid points in each
  693. * direction m1, m2, m3. nt is the number of iterations
  694. */
  695. int nx, ny, nz, maxdim, niter;
  696. if (class == 'S') { nx = 64; ny = 64; nz = 64; niter = 6;}
  697. else if (class == 'W') { nx = 128; ny = 128; nz = 32; niter = 6;}
  698. else if (class == 'A') { nx = 256; ny = 256; nz = 128; niter = 6;}
  699. else if (class == 'B') { nx = 512; ny = 256; nz = 256; niter =20;}
  700. else if (class == 'C') { nx = 512; ny = 512; nz = 512; niter =20;}
  701. else if (class == 'D') { nx = 2048; ny = 1024; nz = 1024; niter =25;}
  702. else if (class == 'E') { nx = 4096; ny = 2048; nz = 2048; niter =25;}
  703. else {
  704. printf("setparams: Internal error: invalid class type %c\n", class);
  705. exit(1);
  706. }
  707. maxdim = nx;
  708. if (ny > maxdim) maxdim = ny;
  709. if (nz > maxdim) maxdim = nz;
  710. fprintf(fp, "#define nx %d\n#define ny %d\n#define nz %d\n#define maxdim %d\n",
  711. nx, ny, nz, maxdim);
  712. fprintf(fp, "#define niter_default %d\n", niter);
  713. fprintf(fp, "#define np_min %d\n", nprocs);
  714. fprintf(fp, "#define ntdivnp (((nx*ny)/np_min)*nz)\n");
  715. fprintf(fp, "static double ntotal_f = 1.e0*nx*ny*nz;\n");
  716. }
  717. /*
  718. * write_ep_info(): Write EP specific info to config file
  719. */
  720. void write_ep_info(FILE *fp, int nprocs, char class)
  721. {
  722. /* easiest way (given the way the benchmark is written)
  723. * is to specify log of number of grid points in each
  724. * direction m1, m2, m3. nt is the number of iterations
  725. */
  726. int m;
  727. if (class == 'S') { m = 24; }
  728. else if (class == 'W') { m = 25; }
  729. else if (class == 'A') { m = 28; }
  730. else if (class == 'B') { m = 30; }
  731. else if (class == 'C') { m = 32; }
  732. else if (class == 'D') { m = 36; }
  733. else if (class == 'E') { m = 40; }
  734. else {
  735. printf("setparams: Internal error: invalid class type %c\n", class);
  736. exit(1);
  737. }
  738. /* number of processors given by "npm" */
  739. fprintf(fp, "static char class =\'%c\';\n",
  740. class);
  741. fprintf(fp, "static int m=%d, npm=%d;\n",
  742. m, nprocs);
  743. }
  744. /*
  745. * This is a gross hack to allow the benchmarks to
  746. * print out how they were compiled. Various other ways
  747. * of doing this have been tried and they all fail on
  748. * some machine - due to a broken "make" program, or
  749. * F77 limitations, of whatever. Hopefully this will
  750. * always work because it uses very portable C. Unfortunately
  751. * it relies on parsing the make.def file - YUK.
  752. * If your machine doesn't have <string.h> or <ctype.h>, happy hacking!
  753. *
  754. */
  755. #define VERBOSE
  756. #define LL 400
  757. #include <stdio.h>
  758. #define DEFFILE "../config/make.def"
  759. #define DEFAULT_MESSAGE "(none)"
  760. FILE *deffile;
  761. void write_compiler_info(int type, FILE *fp)
  762. {
  763. char line[LL];
  764. char mpif77[LL], flink[LL], fmpi_lib[LL], fmpi_inc[LL], fflags[LL], flinkflags[LL];
  765. char compiletime[LL], randfile[LL];
  766. char mpicc[LL], cflags[LL], clink[LL], clinkflags[LL],
  767. cmpi_lib[LL], cmpi_inc[LL];
  768. struct tm *tmp;
  769. time_t t;
  770. deffile = fopen(DEFFILE, "r");
  771. if (deffile == NULL) {
  772. printf("\n\
  773. setparams: File %s doesn't exist. To build the NAS benchmarks\n\
  774. you need to create is according to the instructions\n\
  775. in the README in the main directory and comments in \n\
  776. the file config/make.def.template\n", DEFFILE);
  777. exit(1);
  778. }
  779. strcpy(mpif77, DEFAULT_MESSAGE);
  780. strcpy(flink, DEFAULT_MESSAGE);
  781. strcpy(fmpi_lib, DEFAULT_MESSAGE);
  782. strcpy(fmpi_inc, DEFAULT_MESSAGE);
  783. strcpy(fflags, DEFAULT_MESSAGE);
  784. strcpy(flinkflags, DEFAULT_MESSAGE);
  785. strcpy(randfile, DEFAULT_MESSAGE);
  786. strcpy(mpicc, DEFAULT_MESSAGE);
  787. strcpy(cflags, DEFAULT_MESSAGE);
  788. strcpy(clink, DEFAULT_MESSAGE);
  789. strcpy(clinkflags, DEFAULT_MESSAGE);
  790. strcpy(cmpi_lib, DEFAULT_MESSAGE);
  791. strcpy(cmpi_inc, DEFAULT_MESSAGE);
  792. while (fgets(line, LL, deffile) != NULL) {
  793. if (*line == '#') continue;
  794. /* yes, this is inefficient. but it's simple! */
  795. check_line(line, "MPIF77", mpif77);
  796. check_line(line, "FLINK", flink);
  797. check_line(line, "FMPI_LIB", fmpi_lib);
  798. check_line(line, "FMPI_INC", fmpi_inc);
  799. check_line(line, "FFLAGS", fflags);
  800. check_line(line, "FLINKFLAGS", flinkflags);
  801. check_line(line, "RAND", randfile);
  802. check_line(line, "MPICC", mpicc);
  803. check_line(line, "CFLAGS", cflags);
  804. check_line(line, "CLINK", clink);
  805. check_line(line, "CLINKFLAGS", clinkflags);
  806. check_line(line, "CMPI_LIB", cmpi_lib);
  807. check_line(line, "CMPI_INC", cmpi_inc);
  808. /* if the dummy library is used by including make.dummy, we set the
  809. Fortran and C paths to libraries and headers accordingly */
  810. if(check_include_line(line, "../config/make.dummy")) {
  811. strcpy(fmpi_lib, "-L../MPI_dummy -lmpi");
  812. strcpy(fmpi_inc, "-I../MPI_dummy");
  813. strcpy(cmpi_lib, "-L../MPI_dummy -lmpi");
  814. strcpy(cmpi_inc, "-I../MPI_dummy");
  815. }
  816. }
  817. (void) time(&t);
  818. tmp = localtime(&t);
  819. (void) strftime(compiletime, (size_t)LL, "%d %b %Y", tmp);
  820. switch(type) {
  821. case FT:
  822. case SP:
  823. case BT:
  824. case MG:
  825. case LU:
  826. case EP:
  827. case CG:
  828. put_def_string(fp, "COMPILETIME", compiletime);
  829. put_def_string(fp, "NPBVERSION", VERSION);
  830. put_def_string(fp, "CS1", mpicc);
  831. put_def_string(fp, "CS2", clink);
  832. put_def_string(fp, "CS3", cmpi_lib);
  833. put_def_string(fp, "CS4", cmpi_inc);
  834. put_def_string(fp, "CS5", cflags);
  835. put_def_string(fp, "CS6", clinkflags);
  836. put_def_string(fp, "CS7", randfile);
  837. break;
  838. case IS:
  839. case DT:
  840. put_def_string(fp, "COMPILETIME", compiletime);
  841. put_def_string(fp, "NPBVERSION", VERSION);
  842. put_def_string(fp, "MPICC", mpicc);
  843. put_def_string(fp, "CFLAGS", cflags);
  844. put_def_string(fp, "CLINK", clink);
  845. put_def_string(fp, "CLINKFLAGS", clinkflags);
  846. put_def_string(fp, "CMPI_LIB", cmpi_lib);
  847. put_def_string(fp, "CMPI_INC", cmpi_inc);
  848. break;
  849. default:
  850. printf("setparams: (Internal error): Unknown benchmark type %d\n",
  851. type);
  852. exit(1);
  853. }
  854. }
  855. void check_line(char *line, char *label, char *val)
  856. {
  857. char *original_line;
  858. int n;
  859. original_line = line;
  860. /* compare beginning of line and label */
  861. while (*label != '\0' && *line == *label) {
  862. line++; label++;
  863. }
  864. /* if *label is not EOS, we must have had a mismatch */
  865. if (*label != '\0') return;
  866. /* if *line is not a space, actual label is longer than test label */
  867. if (!isspace(*line) && *line != '=') return ;
  868. /* skip over white space */
  869. while (isspace(*line)) line++;
  870. /* next char should be '=' */
  871. if (*line != '=') return;
  872. /* skip over white space */
  873. while (isspace(*++line));
  874. /* if EOS, nothing was specified */
  875. if (*line == '\0') return;
  876. /* finally we've come to the value */
  877. strcpy(val, line);
  878. /* chop off the newline at the end */
  879. n = strlen(val)-1;
  880. if (n >= 0 && val[n] == '\n')
  881. val[n--] = '\0';
  882. if (n >= 0 && val[n] == '\r')
  883. val[n--] = '\0';
  884. /* treat continuation */
  885. while (val[n] == '\\' && fgets(original_line, LL, deffile)) {
  886. line = original_line;
  887. while (isspace(*line)) line++;
  888. if (isspace(*original_line)) val[n++] = ' ';
  889. while (*line && *line != '\n' && *line != '\r' && n < LL-1)
  890. val[n++] = *line++;
  891. val[n] = '\0';
  892. n--;
  893. }
  894. /* if (val[strlen(val) - 1] == '\\') {
  895. printf("\n\
  896. setparams: Error in file make.def. Because of the way in which\n\
  897. command line arguments are incorporated into the\n\
  898. executable benchmark, you can't have any continued\n\
  899. lines in the file make.def, that is, lines ending\n\
  900. with the character \"\\\". Although it may be ugly, \n\
  901. you should be able to reformat without continuation\n\
  902. lines. The offending line is\n\
  903. %s\n", original_line);
  904. exit(1);
  905. } */
  906. }
  907. int check_include_line(char *line, char *filename)
  908. {
  909. char *include_string = "include";
  910. /* compare beginning of line and "include" */
  911. while (*include_string != '\0' && *line == *include_string) {
  912. line++; include_string++;
  913. }
  914. /* if *include_string is not EOS, we must have had a mismatch */
  915. if (*include_string != '\0') return(0);
  916. /* if *line is not a space, first word is not "include" */
  917. if (!isspace(*line)) return(0);
  918. /* skip over white space */
  919. while (isspace(*++line));
  920. /* if EOS, nothing was specified */
  921. if (*line == '\0') return(0);
  922. /* next keyword should be name of include file in *filename */
  923. while (*filename != '\0' && *line == *filename) {
  924. line++; filename++;
  925. }
  926. if (*filename != '\0' ||
  927. (*line != ' ' && *line != '\0' && *line !='\n')) return(0);
  928. else return(1);
  929. }
  930. #define MAXL 46
  931. void put_string(FILE *fp, char *name, char *val)
  932. {
  933. int len;
  934. len = strlen(val);
  935. if (len > MAXL) {
  936. val[MAXL] = '\0';
  937. val[MAXL-1] = '.';
  938. val[MAXL-2] = '.';
  939. val[MAXL-3] = '.';
  940. len = MAXL;
  941. }
  942. fprintf(fp, "%scharacter*%d %s\n", FINDENT, len, name);
  943. fprintf(fp, "%sparameter (%s=\'%s\')\n", FINDENT, name, val);
  944. }
  945. /* NOTE: is the ... stuff necessary in C? */
  946. void put_def_string(FILE *fp, char *name, char *val)
  947. {
  948. int len;
  949. len = strlen(val);
  950. if (len > MAXL) {
  951. val[MAXL] = '\0';
  952. val[MAXL-1] = '.';
  953. val[MAXL-2] = '.';
  954. val[MAXL-3] = '.';
  955. len = MAXL;
  956. }
  957. fprintf(fp, "#define %s \"%s\"\n", name, val);
  958. }
  959. void put_def_variable(FILE *fp, char *name, char *val)
  960. {
  961. int len;
  962. len = strlen(val);
  963. if (len > MAXL) {
  964. val[MAXL] = '\0';
  965. val[MAXL-1] = '.';
  966. val[MAXL-2] = '.';
  967. val[MAXL-3] = '.';
  968. len = MAXL;
  969. }
  970. fprintf(fp, "#define %s %s\n", name, val);
  971. }
  972. #if 0
  973. /* this version allows arbitrarily long lines but
  974. * some compilers don't like that and they're rarely
  975. * useful
  976. */
  977. #define LINELEN 65
  978. void put_string(FILE *fp, char *name, char *val)
  979. {
  980. int len, nlines, pos, i;
  981. char line[100];
  982. len = strlen(val);
  983. nlines = len/LINELEN;
  984. if (nlines*LINELEN < len) nlines++;
  985. fprintf(fp, "%scharacter*%d %s\n", FINDENT, nlines*LINELEN, name);
  986. fprintf(fp, "%sparameter (%s = \n", FINDENT, name);
  987. for (i = 0; i < nlines; i++) {
  988. pos = i*LINELEN;
  989. if (i == 0) fprintf(fp, "%s\'", CONTINUE);
  990. else fprintf(fp, "%s", CONTINUE);
  991. /* number should be same as LINELEN */
  992. fprintf(fp, "%.65s", val+pos);
  993. if (i == nlines-1) fprintf(fp, "\')\n");
  994. else fprintf(fp, "\n");
  995. }
  996. }
  997. #endif
  998. /* integer square root. Return error if argument isn't
  999. * a perfect square or is less than or equal to zero
  1000. */
  1001. int isqrt(int i)
  1002. {
  1003. int root, square;
  1004. if (i <= 0) return(-1);
  1005. square = 0;
  1006. for (root = 1; square <= i; root++) {
  1007. square = root*root;
  1008. if (square == i) return(root);
  1009. }
  1010. return(-1);
  1011. }
  1012. /* integer log base two. Return error is argument isn't
  1013. * a power of two or is less than or equal to zero
  1014. */
  1015. int ilog2(int i)
  1016. {
  1017. int log2;
  1018. int exp2 = 1;
  1019. if (i <= 0) return(-1);
  1020. for (log2 = 0; log2 < 20; log2++) {
  1021. if (exp2 == i) return(log2);
  1022. exp2 *= 2;
  1023. }
  1024. return(-1);
  1025. }
  1026. int ipow2(int i)
  1027. {
  1028. int pow2 = 1;
  1029. if (i < 0) return(-1);
  1030. if (i == 0) return(1);
  1031. while(i--) pow2 *= 2;
  1032. return(pow2);
  1033. }
  1034. void write_convertdouble_info(int type, FILE *fp)
  1035. {
  1036. switch(type) {
  1037. case SP:
  1038. case BT:
  1039. case LU:
  1040. case FT:
  1041. case MG:
  1042. case EP:
  1043. case CG:
  1044. #ifdef CONVERTDOUBLE
  1045. fprintf(fp, "static int convertdouble = 1;\n");
  1046. #else
  1047. fprintf(fp, "static int convertdouble = 0;\n");
  1048. #endif
  1049. break;
  1050. }
  1051. }