Advertisement
Guest User

codice

a guest
Jan 18th, 2018
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.11 KB | None | 0 0
  1. /**************************************************************************************
  2. *
  3. * CdL Magistrale in Ingegneria Informatica
  4. * Corso di Architetture e Programmazione dei Sistemi di Elaborazione - a.a. 2017/18
  5. *
  6. * Progetto dell'algoritmo di PageRank
  7. * in linguaggio assembly x86-32 + SSE
  8. *
  9. * Fabrizio Angiulli, 23 novembre 2017
  10. *
  11. **************************************************************************************/
  12.  
  13. /*
  14.  
  15. Software necessario per l'esecuzione:
  16.  
  17. NASM (www.nasm.us)
  18. GCC (gcc.gnu.org)
  19.  
  20. entrambi sono disponibili come pacchetti software
  21. installabili mediante il packaging tool del sistema
  22. operativo; per esempio, su Ubuntu, mediante i comandi:
  23.  
  24. sudo apt-get install nasm
  25. sudo apt-get install gcc
  26.  
  27. potrebbe essere necessario installare le seguenti librerie:
  28.  
  29. sudo apt-get install lib32gcc-4.8-dev (o altra versione)
  30. sudo apt-get install libc6-dev-i386
  31.  
  32. Per generare il file eseguibile:
  33.  
  34. nasm -f elf32 pagerank32.nasm && gcc -O0 -m32 -msse pagerank32.o pagerank32c.c -o pagerank32c -lm && ./pagerank32c
  35.  
  36. oppure
  37.  
  38. ./runpagerank32
  39.  
  40. */
  41.  
  42. #include <stdlib.h>
  43. #include <stdio.h>
  44. #include <math.h>
  45. #include <string.h>
  46. #include <time.h>
  47. #include <xmmintrin.h>
  48.  
  49.  
  50. #define MATRIX double*
  51. #define VECTOR double*
  52. #define GRAPH double*
  53.  
  54.  
  55. typedef struct {
  56. int x;
  57. int y;
  58. } location;
  59.  
  60.  
  61. typedef struct {
  62. char* file_name;
  63. MATRIX P; // codifica dense
  64. GRAPH G; // codifica full
  65. int N; // numero di nodi
  66. int M; // numero di archi
  67. double c; // default=0.85
  68. double eps; // default=1e-5
  69. int format; // 0=sparse, 1=full
  70. int prec; // 0=single, 1=double
  71. int opt; // 0=nopt, 1=opt
  72. double* pagerank;
  73. int silent;
  74. int display;
  75. } params;
  76.  
  77.  
  78. /*
  79. *
  80. * Le funzioni sono state scritte assumento che le matrici siano memorizzate
  81. * mediante un array (float*), in modo da occupare un unico blocco
  82. * di memoria, ma a scelta del candidato possono essere
  83. * memorizzate mediante array di array (float**).
  84. *
  85. * L'assunzione corrente è che le matrici siano in row-major order.
  86. *
  87. */
  88.  
  89.  
  90. void* get_block(int size, int elements) {
  91. return _mm_malloc(elements*size,16);
  92. }
  93.  
  94.  
  95. void free_block(void* p) {
  96. _mm_free(p);
  97. }
  98.  
  99.  
  100. MATRIX alloc_matrix(int rows, int cols) {
  101. return (MATRIX) get_block(sizeof(double),rows*cols);
  102. }
  103.  
  104.  
  105. void dealloc_matrix(MATRIX mat) {
  106. free_block(mat);
  107. }
  108.  
  109.  
  110. /*
  111. *
  112. * load_dense
  113. * ===========
  114. *
  115. * Legge da file una matrice di N righe
  116. * e M colonne e la memorizza in un array lineare in row-major order
  117. *
  118. * Codifica del file:
  119. * primi 4 byte: numero di righe (N) --> numero intero a 32 bit
  120. * successivi 4 byte: numero di colonne (M) --> numero intero a 32 bit
  121. * successivi N*M*4 byte: matrix data in row-major order --> numeri floating-point a precisione doppia
  122. *
  123. */
  124. MATRIX load_dense(char* filename, int *n, int *m) {
  125. FILE* fp;
  126. int rows, cols, status, i;
  127. char fpath[256];
  128.  
  129. sprintf(fpath, "%s.matrix", filename);
  130. fp = fopen(fpath, "rb");
  131.  
  132. if (fp == NULL) {
  133. printf("'%s' : bad matrix file name!\n", fpath);
  134. exit(0);
  135. }
  136.  
  137. status = fread(&rows, sizeof(int), 1, fp);
  138. status = fread(&cols, sizeof(int), 1, fp);
  139.  
  140. MATRIX data = alloc_matrix(rows,cols);
  141. status = fread(data, sizeof(double), rows*cols, fp);
  142. fclose(fp);
  143.  
  144. *n = rows;
  145. *m = rows*cols;
  146.  
  147. return data;
  148. }
  149.  
  150. /*
  151. *
  152. * load_sparse
  153. * ===========
  154. *
  155. * Legge da file il grafo
  156. *
  157. * Codifica del file:
  158. * primi 4 byte: numero di nodi (N) --> numero intero
  159. * successivi 4 byte: numero di archi (M) --> numero intero
  160. * successivi M*2*4 byte: M archi rappresentati come coppie (i,j) di interi a 32 bit
  161. *
  162. */
  163. GRAPH load_sparse(char* filename, int *n, int *m) {
  164. FILE* fp;
  165. int nodes, arcs, status, i, j, k;
  166. char fpath[256];
  167. int sorg, dest;
  168.  
  169. sprintf(fpath, "%s.graph", filename);
  170. fp = fopen(fpath, "rb");
  171.  
  172. if (fp == NULL) {
  173. printf("'%s' : bad graph file name!\n", fpath);
  174. exit(0);
  175. }
  176.  
  177. status = fread(&nodes, sizeof(int), 1, fp);
  178. status = fread(&arcs, sizeof(int), 1, fp);
  179.  
  180. //printf("nodi: %d", nodes);
  181. //printf("archi: %d",arcs);
  182.  
  183. GRAPH g = alloc_matrix(nodes,nodes);
  184.  
  185. for ( j=0;j<nodes;j++)
  186. for(k=0;k<nodes;k++)
  187. g[i*nodes+j]=0.0;
  188.  
  189. for (i = 0; i < arcs; i++) {
  190. status = fread(&sorg, sizeof(int), 1, fp);
  191. status = fread(&dest, sizeof(int), 1, fp);
  192. g[sorg*nodes+dest]=1.0;
  193. }
  194. fclose(fp);
  195.  
  196. //for ( j=0;j<nodes;j++)
  197. //printf("colonna: %d \n elemento:%f",j, g[j]);
  198.  
  199. *n = nodes;
  200. *m = arcs;
  201.  
  202. return g;
  203.  
  204. }
  205.  
  206.  
  207. void save_pageranks(char* filename, int n, VECTOR pagerank) {
  208. FILE* fp;
  209. int i;
  210. char fpath[256];
  211.  
  212. sprintf(fpath, "%s_pageranks.txt", filename);
  213. fp = fopen(fpath, "w");
  214. for (i = 0; i < n; i++)
  215. fprintf(fp, "%.14g\n", pagerank[i]);
  216. fclose(fp);
  217. }
  218.  
  219. double* outdegree(GRAPH m, int n){
  220. //serve solo per il caso sparso ecco perchè Graph
  221. int i,j;
  222. double outdegree;
  223. double* v= (double*) get_block(sizeof(double),n);
  224. if(v==NULL){
  225. printf("Memoria non disponibile!");
  226. exit(-1);
  227. }
  228. double nodi=0;
  229. for(i=0;i<n;i++){
  230. outdegree=0;
  231. for(j=0;j<n;j++){
  232. //printf("riga: %d \n colonna:%d \n grado:%f",i,j,outdegree);
  233. outdegree=outdegree+m[i*n+j];
  234. }
  235. v[i]=outdegree;
  236. nodi+=outdegree;
  237. //printf("%f",outdegree);
  238. }
  239. //printf("%f",nodi);
  240. return v;
  241. }
  242.  
  243. void matriceProb(MATRIX p, int n, double* v){
  244. int i,j;
  245. //Calcolo D
  246. MATRIX d=alloc_matrix(n, n);
  247. if(d==NULL){
  248. printf("Memoria non disponibile!");
  249. dealloc_matrix(p);
  250. exit(-1);
  251. }
  252. double k= 1.0/n;
  253. for( i=0;i<n;i++){
  254. for( j=0;j<n;j++){
  255. d[i*n+j]=v[i]*k;
  256. //printf("%g - ",d[i*n+j]);
  257. }
  258. }
  259.  
  260. for( i=0;i<n;i++){
  261. for( j=0;j<n;j++){
  262. p[i*n+j]= p[i*n+j]+d[i*n+j];
  263. //printf("%g - ",p[i*n+j]);
  264. }
  265. }
  266.  
  267. dealloc_matrix(d);
  268.  
  269. }
  270.  
  271. MATRIX matriceTransizione(GRAPH m, int n, double c){
  272. int i,j,k;
  273. double* d=outdegree(m,n);
  274. MATRIX p=alloc_matrix(n, n);
  275. if(p==NULL){
  276. printf("Memoria non disponibile!");
  277. exit(-1);
  278. }
  279.  
  280. for(i=0;i<n;i++){
  281. for(j=0;j<n;j++){
  282. //printf("- %g- ",m[i*n+j]);
  283. if(d[i]!=0.0) p[i*n+j]=m[i*n+j]/d[i];
  284. else p[i*n+j]=0.0;
  285. //printf("%g - ",p[i*n+j]);
  286. }
  287. }
  288.  
  289. //Calcolo il vettore sigma
  290. double* v= (double*) get_block(sizeof(double),n);
  291. if(v==NULL){
  292. printf("Memoria non disponibile!");
  293. dealloc_matrix(p);
  294. exit(-1);
  295. }
  296. for (k=0;k<n;k++){
  297. if(d[k]== 0.0)
  298. v[k]=1.0;
  299. else v[k]=0.0;
  300. }
  301.  
  302. free_block(d);
  303. matriceProb(p,n,v);
  304. free_block(v);
  305.  
  306. double cost=(1.0-c)/n;
  307. printf("%g - ",cost);
  308. for(i=0;i<n;i++){
  309. for(j=0;j<n;j++){
  310. p[i*n+j]= p[i*n+j]*c+cost;
  311. //printf("%g - ",p[i*n+j]);
  312. }
  313. }
  314. return p;
  315. }
  316.  
  317. VECTOR autovettore_single(VECTOR pi,MATRIX p,int n){
  318. int i,j;
  319. float s;
  320. VECTOR r=(VECTOR) get_block(sizeof(float),n);
  321. if(r == NULL){
  322. printf("Memoria non disponibile!");
  323. free(pi);
  324. exit(-1);
  325. }
  326.  
  327. for(i=0;i<n;i++){
  328. s=0;
  329. for(j=0;j<n;j++){
  330. //Si accede a p come se fosse CMO dato che serve la //trasposta
  331. s+=p[i+j*n]*pi[j];
  332. }
  333. r[i]=s;
  334. }
  335. return r;
  336. }
  337.  
  338. VECTOR autovettore_double(VECTOR pi,MATRIX p,int n){
  339.  
  340. int i,j;
  341. double s;
  342. VECTOR r=(VECTOR) get_block(sizeof(double),n);
  343. if(r == NULL){
  344. printf("Memoria non disponibile!");
  345. free(pi);
  346. exit(-1);
  347. }
  348.  
  349. for(i=0;i<n;i++){
  350. s=0;
  351. for(j=0;j<n;j++){
  352. //Si accede a p come se fosse CMO dato che serve la //trasposta
  353. s+=p[i+j*n]*pi[j];
  354. }
  355. r[i]=s;
  356. }
  357. return r;
  358. }
  359.  
  360. double terminationError(VECTOR i,VECTOR j, int n){
  361. int k;
  362. double norma=0.0;
  363. for(k=0;k<n;k++){
  364. double diff=i[k]-j[k];
  365. norma+= diff*diff;
  366. }
  367. return sqrt(norma);
  368. }
  369.  
  370. void powerIteration(VECTOR pi,MATRIX p,int n,double eps,int prec){
  371. VECTOR v;
  372. if(prec==0) v=autovettore_single(pi,p,n);
  373. else autovettore_double(pi,p,n);
  374. double delta=terminationError(v,pi,n);
  375. void* temp;
  376.  
  377. while(delta>eps){
  378. temp=v;
  379. if(prec==0) v=autovettore_single(pi,p,n);
  380. else autovettore_double(pi,p,n);
  381. pi=temp;
  382. delta=terminationError(v,pi,n);
  383. }
  384.  
  385. pi=v;
  386. }
  387.  
  388. extern void pagerank32(params* input); //funzione assembly
  389.  
  390. void pagerank(params* input) {
  391.  
  392. if (input->format == 0) input->P = matriceTransizione(input->G, input->N , input->c);
  393.  
  394. if(input->opt==1)pagerank32(input); // Chiamata alla funzione assembly
  395. else{
  396. int i;
  397. VECTOR v;
  398. //VECTOR è un double*...è corretto così?
  399. if (input->prec== 0)
  400. v=(VECTOR) get_block(sizeof(float),input->N);
  401. else v=(VECTOR) get_block(sizeof(double),input->N);
  402.  
  403. if(v==NULL){
  404. printf("Memoria non disponibile!");
  405. free(input); //Il main lo rialloca??
  406. exit(-1);
  407. }
  408. //inizializzazione di v
  409. for(i=0; i<input->N; i++)
  410. v[i]=1/input->N;
  411. powerIteration(v,input->P,input->N,input->eps,input->prec);
  412. input->pagerank=v;
  413. }
  414. }
  415.  
  416.  
  417. #define SPARSE 0
  418. #define DENSE 1
  419. #define SINGLE 0
  420. #define DOUBLE 1
  421. #define NOPT 0
  422. #define OPT 1
  423.  
  424.  
  425.  
  426. int main(int argc, char** argv) {
  427.  
  428. params* input = malloc(sizeof(params));
  429.  
  430. input->file_name = NULL;
  431. input->P = NULL; // dense format
  432. input->G = NULL; // sparse format
  433. input->N = 0; // number of nodes
  434. input->M = 0; // number of arcs
  435. input->c = 0.85;
  436. input->eps = 1e-5;
  437. input->format = SPARSE; // 0=sparse, 1=dense
  438. input->prec = SINGLE; // 0=single, 1=double
  439. input->opt = NOPT; // 0=nopt, 1=opt
  440. input->silent = 0; // 0=false,<>0=true
  441. input->display = 0; // 0=false <>0=true
  442.  
  443. int i, j;
  444.  
  445. int par = 1;
  446. while (par < argc) {
  447. if (par == 1) {
  448. input->file_name = argv[par];
  449. par++;
  450. } else if (strcmp(argv[par],"-s") == 0) {
  451. input->silent = 1;
  452. par++;
  453. } else if (strcmp(argv[par],"-d") == 0) {
  454. input->display = 1;
  455. par++;
  456. } else if (strcmp(argv[par],"-c") == 0) {
  457. par++;
  458. if (par >= argc) {
  459. printf("Missing c value!\n");
  460. exit(1);
  461. }
  462. input->c = atof(argv[par]);
  463. par++;
  464. } else if (strcmp(argv[par],"-eps") == 0) {
  465. par++;
  466. if (par >= argc) {
  467. printf("Missing eps value!\n");
  468. exit(1);
  469. }
  470. input->eps = atof(argv[par]);
  471. par++;
  472. } else if (strcmp(argv[par],"-sparse") == 0) {
  473. input->format = SPARSE;
  474. par++;
  475. } else if (strcmp(argv[par],"-dense") == 0) {
  476. input->format = DENSE;
  477. par++;
  478. } else if (strcmp(argv[par],"-single") == 0) {
  479. input->prec = SINGLE;
  480. par++;
  481. } else if (strcmp(argv[par],"-double") == 0) {
  482. input->prec = DOUBLE;
  483. par++;
  484. } else if (strcmp(argv[par],"-nopt") == 0) {
  485. input->opt = NOPT;
  486. par++;
  487. } else if (strcmp(argv[par],"-opt") == 0) {
  488. input->opt = OPT;
  489. par++;
  490. } else
  491. par++;
  492. }
  493.  
  494. if (!input->silent) {
  495. printf("Usage: %s <input_file_name> [-d][-s][-sparse|-dense][-single|-double][-nopt|-opt][-c <value>][-eps <value>]\n", argv[0]);
  496. printf("\nParameters:\n");
  497. printf("\t-d : display input and output\n");
  498. printf("\t-s : silent\n");
  499. printf("\t-sparse/-full: input format (sparse=list of arcs,full=matrix)\n");
  500. printf("\t-single/-double: floating-point precision (only sparse format)\n");
  501. printf("\t-nopt/-opt: disable/enable optimizations\n");
  502. printf("\t-c <value> : 1-teleportation_probability (default 0.85)\n");
  503. printf("\t-eps <value> : termination error (default 1e-5)\n");
  504. printf("\n");
  505. }
  506.  
  507. if (input->file_name == NULL || strlen(input->file_name) == 0) {
  508. printf("Missing input file name!\n");
  509. exit(1);
  510. }
  511.  
  512. if (input->format == 0)
  513. input->G = load_sparse(input->file_name, &input->N, &input->M);
  514. else
  515. input->P = load_dense(input->file_name, &input->N, &input->M);
  516.  
  517. if (!input->silent) {
  518. printf("Input file name: '%s'\n", input->file_name);
  519. printf("Number of nodes: %d\n", input->N);
  520. printf("Number of arcs: %d\n", input->M);
  521. printf("Parameter c: %f\n", input->c);
  522. printf("Parameter eps: %f\n", input->eps);
  523. }
  524.  
  525. clock_t t = clock();
  526. pagerank(input);
  527. t = clock() - t;
  528.  
  529. if (!input->silent)
  530. printf("\nExecution time = %.3f seconds\n", ((float)t)/CLOCKS_PER_SEC);
  531. else
  532. printf("%.3f\n", ((float)t)/CLOCKS_PER_SEC);
  533.  
  534. if (input->pagerank != NULL)
  535. {
  536. if (!input->silent && input->display) {
  537. printf("\nPageRanks:\n");
  538. for (i = 0; i < input->N; i++) {
  539. printf("%d %.14g\n", i+1, input->pagerank[i]);
  540. }
  541. }
  542. save_pageranks(input->file_name, input->N, input->pagerank);
  543. }
  544.  
  545. return 0;
  546. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement