{"action":"created","issue":{"url":"https://api.github.com/repos/leonardoaraujosantos/DLMatFramework/issues/19","repository_url":"https://api.github.com/repos/leonardoaraujosantos/DLMatFramework","labels_url":"https://api.github.com/repos/leonardoaraujosantos/DLMatFramework/issues/19/labels{/name}","comments_url":"https://api.github.com/repos/leonardoaraujosantos/DLMatFramework/issues/19/comments","events_url":"https://api.github.com/repos/leonardoaraujosantos/DLMatFramework/issues/19/events","html_url":"https://github.com/leonardoaraujosantos/DLMatFramework/issues/19","id":206336516,"number":19,"title":"Improve im2col performance","user":{"login":"leonardoaraujosantos","id":898383,"avatar_url":"https://avatars.githubusercontent.com/u/898383?v=3","gravatar_id":"","url":"https://api.github.com/users/leonardoaraujosantos","html_url":"https://github.com/leonardoaraujosantos","followers_url":"https://api.github.com/users/leonardoaraujosantos/followers","following_url":"https://api.github.com/users/leonardoaraujosantos/following{/other_user}","gists_url":"https://api.github.com/users/leonardoaraujosantos/gists{/gist_id}","starred_url":"https://api.github.com/users/leonardoaraujosantos/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/leonardoaraujosantos/subscriptions","organizations_url":"https://api.github.com/users/leonardoaraujosantos/orgs","repos_url":"https://api.github.com/users/leonardoaraujosantos/repos","events_url":"https://api.github.com/users/leonardoaraujosantos/events{/privacy}","received_events_url":"https://api.github.com/users/leonardoaraujosantos/received_events","type":"User","site_admin":false},"labels":[{"id":509287343,"url":"https://api.github.com/repos/leonardoaraujosantos/DLMatFramework/labels/enhancement","name":"enhancement","color":"84b6eb","default":true}],"state":"open","locked":false,"assignee":{"login":"leonardoaraujosantos","id":898383,"avatar_url":"https://avatars.githubusercontent.com/u/898383?v=3","gravatar_id":"","url":"https://api.github.com/users/leonardoaraujosantos","html_url":"https://github.com/leonardoaraujosantos","followers_url":"https://api.github.com/users/leonardoaraujosantos/followers","following_url":"https://api.github.com/users/leonardoaraujosantos/following{/other_user}","gists_url":"https://api.github.com/users/leonardoaraujosantos/gists{/gist_id}","starred_url":"https://api.github.com/users/leonardoaraujosantos/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/leonardoaraujosantos/subscriptions","organizations_url":"https://api.github.com/users/leonardoaraujosantos/orgs","repos_url":"https://api.github.com/users/leonardoaraujosantos/repos","events_url":"https://api.github.com/users/leonardoaraujosantos/events{/privacy}","received_events_url":"https://api.github.com/users/leonardoaraujosantos/received_events","type":"User","site_admin":false},"assignees":[{"login":"leonardoaraujosantos","id":898383,"avatar_url":"https://avatars.githubusercontent.com/u/898383?v=3","gravatar_id":"","url":"https://api.github.com/users/leonardoaraujosantos","html_url":"https://github.com/leonardoaraujosantos","followers_url":"https://api.github.com/users/leonardoaraujosantos/followers","following_url":"https://api.github.com/users/leonardoaraujosantos/following{/other_user}","gists_url":"https://api.github.com/users/leonardoaraujosantos/gists{/gist_id}","starred_url":"https://api.github.com/users/leonardoaraujosantos/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/leonardoaraujosantos/subscriptions","organizations_url":"https://api.github.com/users/leonardoaraujosantos/orgs","repos_url":"https://api.github.com/users/leonardoaraujosantos/repos","events_url":"https://api.github.com/users/leonardoaraujosantos/events{/privacy}","received_events_url":"https://api.github.com/users/leonardoaraujosantos/received_events","type":"User","site_admin":false}],"milestone":{"url":"https://api.github.com/repos/leonardoaraujosantos/DLMatFramework/milestones/2","html_url":"https://github.com/leonardoaraujosantos/DLMatFramework/milestone/2","labels_url":"https://api.github.com/repos/leonardoaraujosantos/DLMatFramework/milestones/2/labels","id":2282953,"number":2,"title":"Version 0.2","description":"","creator":{"login":"leonardoaraujosantos","id":898383,"avatar_url":"https://avatars.githubusercontent.com/u/898383?v=3","gravatar_id":"","url":"https://api.github.com/users/leonardoaraujosantos","html_url":"https://github.com/leonardoaraujosantos","followers_url":"https://api.github.com/users/leonardoaraujosantos/followers","following_url":"https://api.github.com/users/leonardoaraujosantos/following{/other_user}","gists_url":"https://api.github.com/users/leonardoaraujosantos/gists{/gist_id}","starred_url":"https://api.github.com/users/leonardoaraujosantos/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/leonardoaraujosantos/subscriptions","organizations_url":"https://api.github.com/users/leonardoaraujosantos/orgs","repos_url":"https://api.github.com/users/leonardoaraujosantos/repos","events_url":"https://api.github.com/users/leonardoaraujosantos/events{/privacy}","received_events_url":"https://api.github.com/users/leonardoaraujosantos/received_events","type":"User","site_admin":false},"open_issues":8,"closed_issues":6,"state":"open","created_at":"2017-01-27T18:17:33Z","updated_at":"2017-02-09T00:52:24Z","due_on":null,"closed_at":null},"comments":3,"created_at":"2017-02-08T21:54:02Z","updated_at":"2017-02-09T16:57:46Z","closed_at":null,"body":"## Introduction\r\nCreate a mex version of the im2col (Try to use openmp to parallelize some of the for loops)\r\n\r\n## Current profile\r\n![timespent](https://cloud.githubusercontent.com/assets/898383/22759082/17a4778e-ee49-11e6-86da-f69ac69affbd.png)\r\n\r\n## Times\r\nOn the MNIST dataset (28x28x1) it's taking 14.7 seconds during 1000 forward/backward propagation on CPU.\r\nChanging to mex version on CPU single threaded the time goes down to 9.3 seconds\r\n\r\n## Profile after im2col mex\r\n![changemex](https://cloud.githubusercontent.com/assets/898383/22762825/3137dab4-ee59-11e6-81a4-49c567f101a6.png)\r\n\r\n"},"comment":{"url":"https://api.github.com/repos/leonardoaraujosantos/DLMatFramework/issues/comments/278703288","html_url":"https://github.com/leonardoaraujosantos/DLMatFramework/issues/19#issuecomment-278703288","issue_url":"https://api.github.com/repos/leonardoaraujosantos/DLMatFramework/issues/19","id":278703288,"user":{"login":"leonardoaraujosantos","id":898383,"avatar_url":"https://avatars.githubusercontent.com/u/898383?v=3","gravatar_id":"","url":"https://api.github.com/users/leonardoaraujosantos","html_url":"https://github.com/leonardoaraujosantos","followers_url":"https://api.github.com/users/leonardoaraujosantos/followers","following_url":"https://api.github.com/users/leonardoaraujosantos/following{/other_user}","gists_url":"https://api.github.com/users/leonardoaraujosantos/gists{/gist_id}","starred_url":"https://api.github.com/users/leonardoaraujosantos/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/leonardoaraujosantos/subscriptions","organizations_url":"https://api.github.com/users/leonardoaraujosantos/orgs","repos_url":"https://api.github.com/users/leonardoaraujosantos/repos","events_url":"https://api.github.com/users/leonardoaraujosantos/events{/privacy}","received_events_url":"https://api.github.com/users/leonardoaraujosantos/received_events","type":"User","site_admin":false},"created_at":"2017-02-09T16:57:46Z","updated_at":"2017-02-09T16:57:46Z","body":"## TODO\r\nChange im2col to use chrono C++11 features, but first check how it will work on 2016b release\r\n```C++\r\n#include <stdio.h>\r\n#include <time.h>\r\n#include <stdlib.h>\r\n#include <chrono>\r\n\r\nusing namespace std;\r\n\r\n/*\r\nDefine macros to help addressing 1d arrays with 2d coordinates\r\nboth on row-major(C) or col-major(matlab)\r\nWith i:(row coordinate) and j:(col coordinate)\r\nRow major (C)\r\nA[i][j] == A[(i*num_cols_A)+j]\r\nCol major (Matlab)\r\nA[i][j] == A[(j*num_rows_A)+i]\r\n*/\r\n#ifdef USE_ROW_MAJOR\r\n#define MAT_2D(i, j, width) (((i) * (width)) + (j))\r\n#define MAT_3D(i, j, k, height, width)                                         \\\r\n(((i) * (width)) + (j) + ((k) * (height) * (width)))\r\n#else\r\n#define MAT_2D(i, j, height) (((j) * (height)) + (i))\r\n#define MAT_3D(i, j, k, height, width)                                         \\\r\n(((j) * (height)) + (i) + ((k) * (height) * (width)))\r\n#endif\r\n\r\ntemplate <typename T>\r\nvoid im2col(T *data_im, int channels, int height, int width, int ky, int kx, int stride, int pad, T *data_col, double *execTime, double *trfTime) {\r\n\r\n  /*Clear scren to help debug*/\r\n  /*system(\"clear\");*/\r\n\r\n  /*\r\n  We need a stride (positive and non-zero)\r\n  */\r\n  if (!stride) return;\r\n\r\n  /* these tell us how many kernel windows we have across the input image */\r\n  int height_col = (height + (2 * pad) - ky) / stride + 1;\r\n  int width_col = (width + (2 * pad) - kx) / stride + 1;\r\n\r\n  /* Detect fractional size convolution */\r\n  float frac_height = ((float)height + (2.0 * (float)pad) - (float)ky) / (float)stride + 1.0;\r\n  float frac_width = ((float)width + (2.0 * (float)pad) - (float)kx) / (float)stride + 1.0;\r\n  int isFract = 0;\r\n  if ( ((frac_height - (int)frac_height) == 0) && ((frac_width - (int)frac_width) == 0) ){\r\n    isFract = 0;\r\n  } else {\r\n    isFract = 1;\r\n  }\r\n\r\n  /*printf(\"***************************NEW RUN******************************\\n\");\r\n  printf(\"height=%d width=%d Stride=%d Pad=%d K=%d isFract=%d\\n\",height,width,stride,pad,kx,isFract);\r\n  printf(\"height_col=%d width_col=%d\\n\",height_col,width_col);*/\r\n\r\n  /*\r\n  Calculate biggest row/col size considering padding or fractional convolution\r\n  */\r\n  int maxHeight = height - isFract + ((2 * pad)-1);\r\n  int maxWidth = width - isFract + ((2 * pad)-1);\r\n  /*printf(\"Maximum possible coordinates rows=%d Max cols=%d\\n\",maxHeight,maxWidth);*/\r\n\r\n  /* Calculate how tall the collumn will be */\r\n  int cols_height = channels * kx * ky;\r\n  int kernelProd = kx * ky;\r\n\r\n  /*\r\n  Create variables to support richard formula, that calculates idxCol_out\r\n  from (n_rows,n_cols,row,col,ky,kx,stride,width_col)\r\n  Number of collumns that your slide window will cross on\r\n  each dimension.\r\n  Product k(x,y) * stride, calculating outside to avoid this multiplication\r\n  for every row,col,channel\r\n  */\r\n  int n_cols = width_col * kx;\r\n  int n_rows = height_col * ky;\r\n  int prod_ky_stride = ky * stride;\r\n  int prod_kx_stride = kx * stride;\r\n\r\n  /*\r\n  * data_col\r\n  * Will be a 2d matrix [cols_height x (height_col*width_col)]\r\n  */\r\n  int with_data_col = height_col * width_col;\r\n\r\n  /* Measure elapsed wall time */\r\n  struct timespec now, tmstart;\r\n  /*tic*/\r\n\tauto start = chrono::steady_clock::now();\r\n\r\n  int channel,row,col;\r\n\r\n  /* Iterate on the input image (could be virtually padded) */\r\n  #pragma omp parallel for\r\n  for (channel = 0; channel < channels; channel++) {\r\n    /* Move down on the image */\r\n    for (row = 0; row < height + (2 * pad); row += stride) {\r\n      /* Move left on the image */\r\n      for (col = 0; col < width + (2 * pad); col += stride) {\r\n        /*printf(\"-----------------Coordinate [%d x %d]---------------\\n\",row,col);*/\r\n        /*\r\n        If the window is out of the image we should ignore the current\r\n        iteration. But take care that this also may happen when we have\r\n        padding, so check. Because if even with padding we go out of the\r\n        window we should ignore(continue).\r\n        */\r\n        /*printf(\"Calculated window coverage: row=%d col=%d\\n\",(row + (ky-1) - 0),(col + (kx-1) - 0));*/\r\n        if (((row + (ky-1)) > maxHeight) || ((col + (kx-1)) > maxWidth)) {\r\n          /*printf(\"Out of window Coordinate [%d x %d] K:%d pad:%d Image[%d x %d]\\n\",row,col,kx,pad,height,width);*/\r\n          continue;\r\n        }\r\n\r\n        /* Position the row of output channel related to the current channel */\r\n        int idxRow_out = channel * (kernelProd);\r\n        /*\r\n        X coordinate on output 2d matrix (Move right on output matrix)\r\n        Richard formula to calculate the collumn position of the output matrix\r\n        given (n_rows,n_cols,row,col,ky,kx,stride,width_col). Previously this\r\n        was calculated as \"idxCol_out = (idxCol_out + 1) % with_data_col;\"\r\n        after each window slide, but this was breaking full parallelization.\r\n        */\r\n        int idxCol_out = ((n_rows - (n_rows - row*ky))/(prod_ky_stride))*width_col + ((n_cols - (n_cols - col*kx)))/(prod_kx_stride) ;\r\n        int m,n;\r\n        /* Select window [ky x kx] on input volume on each channel */\r\n        for (m = 0; m < ky; m++) {\r\n          for (n = 0; n < kx; n++) {\r\n            /*\r\n            Use on OpenCl\r\n            int idxRow_out = (channel * (kernelProd)) + (m*ky) + n;\r\n            */\r\n            /*\r\n            Fix offset if we're doing padding\r\n            */\r\n            int row_pad = (row + n) - pad;\r\n            int col_pad = (col + m) - pad;\r\n            /* Avoid running out of input image boundaries */\r\n            if ((row_pad >= 0) && (col_pad >= 0) && (row_pad < height) && (col_pad < width)) {\r\n              data_col[MAT_2D(idxRow_out, idxCol_out, cols_height)] =\r\n              data_im[MAT_3D(row_pad, col_pad, channel, height, width)];\r\n              /*printf(\"Adding valid elements %f\\n\",data_im[MAT_3D(row_pad, col_pad, channel, height, width)]);*/\r\n            } else {\r\n              /* If we're out return 0 */\r\n              data_col[MAT_2D(idxRow_out, idxCol_out, cols_height)] = 0;\r\n\r\n            }\r\n            /*\r\n            Move down on the output 2d array to add current element\r\n            from the patch\r\n            */\r\n            idxRow_out++;\r\n          }\r\n        }\r\n      }\r\n    }\r\n  }\r\n\r\n  /*toc*/\r\n  auto end = chrono::steady_clock::now();\r\n  auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);\r\n  *execTime = (double)elapsed.count();\r\n  *trfTime = 0.0;\r\n}\r\n\r\n// Explicit declare available versions to avoid linker error.\r\ntemplate void im2col<double>(double* data_im, int channels,  int height,  int width, int ky, int kx, int stride, int pad, double* data_col, double *execTime, double *trfTime);\r\ntemplate void im2col<float>(float* data_im, int channels,  int height,  int width, int ky, int kx, int stride, int pad, float* data_col, double *execTime, double *trfTime);\r\n\r\n```"}}
{"actor":{"display_login":"leonardoaraujosantos"}}