{"action":"created","comment":{"url":"https://api.github.com/repos/opesci/devito/pulls/comments/74418808","id":74418808,"diff_hunk":"@@ -0,0 +1,223 @@\n+import math\n+import random\n+from os import mkdir, path\n+\n+import cpuinfo\n+\n+import logger\n+\n+# global vars\n+final_report_name = \"final_report.txt\"\n+default_at_dir = path.join(path.dirname(path.realpath(__file__)), \"At Report\")\n+\n+\n+class AutoTuner(object):\n+\n+    def __init__(self, operator, at_report_dir=None):\n+        \"\"\"\n+        Object responsible for auto tuning block sizes.\n+        :param operator: Operator object.\n+        :param at_report_dir: string - indicating path to auto tuning report directory.\n+                              If not set default at report directory is used\n+        :raises ValueError: if operator is not of Operator type\n+        \"\"\"\n+        global final_report_name, default_at_dir\n+\n+        from operator import Operator\n+        if not isinstance(operator, Operator):\n+            raise ValueError(\"Auto tuner requires Operator object to be passed as an argument\")\n+\n+        self.op = operator\n+        self.op.propagator.profile = True\n+        self.op.apply()  # want to run function at least once to set the arguments\n+\n+        self.report_dir = at_report_dir if at_report_dir is not None else default_at_dir\n+        self.final_report_path = path.join(self.report_dir, final_report_name)\n+\n+        if not path.isdir(self.report_dir):  # Creates report dir if does not exist\n+            mkdir(self.report_dir)\n+\n+    @staticmethod\n+    def get_at_block_size(f_name, time_order, spc_border, shape, block_dims, at_report_dir=None):\n+        \"\"\"\n+        Gets block size from auto tuning report\n+        :param f_name: str - function name. Used for naming\n+        :param time_order: int - time order of kernel\n+        :param spc_border: int - space border of kernel\n+        :param shape: list - shape of the data buffer\n+        :param block_dims: list - indicating which dims are blocked.\n+        :param at_report_dir: string - indicating path to auto tuning report directory.\n+                              If not set default at report directory is used\n+        :raises ValueError: if auto tuning report is not found\n+        \"\"\"\n+        global final_report_name, default_at_dir\n+\n+        report_dir = at_report_dir if at_report_dir is not None else default_at_dir\n+        final_report_path = path.join(report_dir, final_report_name)\n+\n+        if not path.isfile(final_report_path):\n+            raise ValueError(\"Auto tuning report at %s not found\" % final_report_path)\n+\n+        # Cache blocking dimensions\n+        cb_dims = str([True if block else False for block in block_dims]).replace(\" \", '')\n+        # model description string\n+        model_descr_str = \"%s %d %d %s %s\" % (f_name, time_order, spc_border,\n+                                              str(shape).replace(\" \", ''), cb_dims)\n+\n+        with open(final_report_path, 'r') as f:\n+            for line in f.readlines():\n+\n+                if model_descr_str in line:\n+                    blocks_str = line.split(' ')[5]\n+                    block_split = blocks_str[1:len(blocks_str) - 2].split(',')\n+\n+                    return [int(block) if block != \"None\" else None for block in block_split]\n+\n+        return None  # returns none if no matching block size was found\n+\n+    @staticmethod\n+    def get_optimal_block_size(shape, load_c):\n+        \"\"\"\n+        Gets optimal block size based on architecture\n+        :param shape: list - shape of the data buffer\n+        :param load_c: int - load count\n+        :return: optimal block size\n+        \"\"\"\n+        cache_s = int(cpuinfo.get_cpu_info()['l2_cache_size'].split(' ')[0])  # cache size\n+        core_c = cpuinfo.get_cpu_info()['count']  # number of cores\n+\n+        # assuming no prefetching, square block will give the most cache reuse.\n+        # We then take the cache/core divide by the size of the inner most dimension in which we do not block.\n+        #  This gives us the X*Y block space, of which we take the square root to get the size of our blocks.\n+        # ((C size / cores) / (4 * length inner most * kernel loads)\n+        optimal_b_size = math.sqrt(((1000 * cache_s) / core_c) / (4 * shape[len(shape) - 1] * load_c))\n+        return int(round(optimal_b_size))  # rounds to the nearest integer\n+\n+    def auto_tune_blocks(self, minimum=5, maximum=20):\n+        \"\"\"\n+        Auto tunes block sizes. Times all block size combinations withing given range and writes it into report\n+        :param minimum: int (optional) - minimum value for auto tuning range. Default 5\n+        :param maximum: int (optional) - maximum value for auto tuning range. Default 20\n+        :raises ValueError: if  minimum is >= maximum\n+        :raises EnvironmentError: If cache blocking is not set inside the Operator object\n+        \"\"\"\n+        if minimum >= maximum:\n+            raise ValueError(\"Invalid parameters. Minimum tune range has to be less than maximum\")\n+\n+        if not self.op.propagator.cache_blocking:\n+            raise EnvironmentError(\"Invalid parameters. Cache_blocking is set to False\")\n+\n+        logger.info(\"Starting auto tuning of block sizes using brute force\")\n+\n+        if maximum - minimum > 2:  # No point to estimate if diff is below 2.\n+            self._estimate_run_time(minimum, maximum)\n+\n+        times = []  # list where times and block sizes will be kept\n+        block_list = []  # used to make sure we do not test the same block sizes\n+        org_block_sizes = self.op.propagator.block_sizes\n+        blocks = list(self.op.propagator.block_sizes)\n+\n+        for x in range(minimum, maximum):\n+            blocks[0] = x if org_block_sizes[0] else None","path":"devito/at_controller.py","position":121,"original_position":121,"commit_id":"aeeee5c3dc660eabd407a23cd928816261daab8d","original_commit_id":"aeeee5c3dc660eabd407a23cd928816261daab8d","user":{"login":"sheino","id":5637480,"avatar_url":"https://avatars.githubusercontent.com/u/5637480?v=3","gravatar_id":"","url":"https://api.github.com/users/sheino","html_url":"https://github.com/sheino","followers_url":"https://api.github.com/users/sheino/followers","following_url":"https://api.github.com/users/sheino/following{/other_user}","gists_url":"https://api.github.com/users/sheino/gists{/gist_id}","starred_url":"https://api.github.com/users/sheino/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sheino/subscriptions","organizations_url":"https://api.github.com/users/sheino/orgs","repos_url":"https://api.github.com/users/sheino/repos","events_url":"https://api.github.com/users/sheino/events{/privacy}","received_events_url":"https://api.github.com/users/sheino/received_events","type":"User","site_admin":false},"body":"`namedtuple` elements are immutable, thus I would have to create new tuple on each iteration instead of just modifying it on a fly","created_at":"2016-08-11T13:12:58Z","updated_at":"2016-08-11T13:12:58Z","html_url":"https://github.com/opesci/devito/pull/78#discussion_r74418808","pull_request_url":"https://api.github.com/repos/opesci/devito/pulls/78","_links":{"self":{"href":"https://api.github.com/repos/opesci/devito/pulls/comments/74418808"},"html":{"href":"https://github.com/opesci/devito/pull/78#discussion_r74418808"},"pull_request":{"href":"https://api.github.com/repos/opesci/devito/pulls/78"}}},"pull_request":{"url":"https://api.github.com/repos/opesci/devito/pulls/78","id":80470479,"html_url":"https://github.com/opesci/devito/pull/78","diff_url":"https://github.com/opesci/devito/pull/78.diff","patch_url":"https://github.com/opesci/devito/pull/78.patch","issue_url":"https://api.github.com/repos/opesci/devito/issues/78","number":78,"state":"open","locked":false,"title":"Auto tuning v3","user":{"login":"sheino","id":5637480,"avatar_url":"https://avatars.githubusercontent.com/u/5637480?v=3","gravatar_id":"","url":"https://api.github.com/users/sheino","html_url":"https://github.com/sheino","followers_url":"https://api.github.com/users/sheino/followers","following_url":"https://api.github.com/users/sheino/following{/other_user}","gists_url":"https://api.github.com/users/sheino/gists{/gist_id}","starred_url":"https://api.github.com/users/sheino/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sheino/subscriptions","organizations_url":"https://api.github.com/users/sheino/orgs","repos_url":"https://api.github.com/users/sheino/repos","events_url":"https://api.github.com/users/sheino/events{/privacy}","received_events_url":"https://api.github.com/users/sheino/received_events","type":"User","site_admin":false},"body":"Adding auto tuning of block sizes feature, which is made to be more general and potentially could be easily extended.\r\n\r\nAdded `AutoTuner` object which takes `Operator` and `at_report_dir_path` as parameters.\r\nTo use auto tuning results pass `cache_bloking` and `at_report` argumenst to `Operator`.\r\nAdded tests and auto tuning example file.\r\nUpdated README.md\r\nAdded `info` function to `logger` as @FabioLuporini suggested\r\n\r\nChanged cache blocking logic, which is as follows:\r\nNow  `cache_blocking`  has to be either single int instance which will block all dims except inner most or list of same size as spacial domain explicitly specifying which dims to block and which block sizes to use.\r\n\r\nIf 0 is passed as ant arg for `cache_blocking` then best guess based on architecture is used for block size\r\n\r\nWhen cache blocking\\auto tuning all block sizes are replaced by variables which are passed as arguments to the function and loop limits are calculated on run time.\r\n\r\nP.s this PR is rebased onto PR 82 which fixes the bug I was encountering.","created_at":"2016-08-08T15:25:44Z","updated_at":"2016-08-11T13:12:58Z","closed_at":null,"merged_at":null,"merge_commit_sha":"d4b6c556c7e86a2e354331a7e646df94eb2363f8","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/opesci/devito/pulls/78/commits","review_comments_url":"https://api.github.com/repos/opesci/devito/pulls/78/comments","review_comment_url":"https://api.github.com/repos/opesci/devito/pulls/comments{/number}","comments_url":"https://api.github.com/repos/opesci/devito/issues/78/comments","statuses_url":"https://api.github.com/repos/opesci/devito/statuses/aeeee5c3dc660eabd407a23cd928816261daab8d","head":{"label":"opesci:auto_tuning_v3","ref":"auto_tuning_v3","sha":"aeeee5c3dc660eabd407a23cd928816261daab8d","user":{"login":"opesci","id":10018551,"avatar_url":"https://avatars.githubusercontent.com/u/10018551?v=3","gravatar_id":"","url":"https://api.github.com/users/opesci","html_url":"https://github.com/opesci","followers_url":"https://api.github.com/users/opesci/followers","following_url":"https://api.github.com/users/opesci/following{/other_user}","gists_url":"https://api.github.com/users/opesci/gists{/gist_id}","starred_url":"https://api.github.com/users/opesci/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/opesci/subscriptions","organizations_url":"https://api.github.com/users/opesci/orgs","repos_url":"https://api.github.com/users/opesci/repos","events_url":"https://api.github.com/users/opesci/events{/privacy}","received_events_url":"https://api.github.com/users/opesci/received_events","type":"Organization","site_admin":false},"repo":{"id":54585666,"name":"devito","full_name":"opesci/devito","owner":{"login":"opesci","id":10018551,"avatar_url":"https://avatars.githubusercontent.com/u/10018551?v=3","gravatar_id":"","url":"https://api.github.com/users/opesci","html_url":"https://github.com/opesci","followers_url":"https://api.github.com/users/opesci/followers","following_url":"https://api.github.com/users/opesci/following{/other_user}","gists_url":"https://api.github.com/users/opesci/gists{/gist_id}","starred_url":"https://api.github.com/users/opesci/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/opesci/subscriptions","organizations_url":"https://api.github.com/users/opesci/orgs","repos_url":"https://api.github.com/users/opesci/repos","events_url":"https://api.github.com/users/opesci/events{/privacy}","received_events_url":"https://api.github.com/users/opesci/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/opesci/devito","description":"Code generation for the inversion workflow","fork":false,"url":"https://api.github.com/repos/opesci/devito","forks_url":"https://api.github.com/repos/opesci/devito/forks","keys_url":"https://api.github.com/repos/opesci/devito/keys{/key_id}","collaborators_url":"https://api.github.com/repos/opesci/devito/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/opesci/devito/teams","hooks_url":"https://api.github.com/repos/opesci/devito/hooks","issue_events_url":"https://api.github.com/repos/opesci/devito/issues/events{/number}","events_url":"https://api.github.com/repos/opesci/devito/events","assignees_url":"https://api.github.com/repos/opesci/devito/assignees{/user}","branches_url":"https://api.github.com/repos/opesci/devito/branches{/branch}","tags_url":"https://api.github.com/repos/opesci/devito/tags","blobs_url":"https://api.github.com/repos/opesci/devito/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/opesci/devito/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/opesci/devito/git/refs{/sha}","trees_url":"https://api.github.com/repos/opesci/devito/git/trees{/sha}","statuses_url":"https://api.github.com/repos/opesci/devito/statuses/{sha}","languages_url":"https://api.github.com/repos/opesci/devito/languages","stargazers_url":"https://api.github.com/repos/opesci/devito/stargazers","contributors_url":"https://api.github.com/repos/opesci/devito/contributors","subscribers_url":"https://api.github.com/repos/opesci/devito/subscribers","subscription_url":"https://api.github.com/repos/opesci/devito/subscription","commits_url":"https://api.github.com/repos/opesci/devito/commits{/sha}","git_commits_url":"https://api.github.com/repos/opesci/devito/git/commits{/sha}","comments_url":"https://api.github.com/repos/opesci/devito/comments{/number}","issue_comment_url":"https://api.github.com/repos/opesci/devito/issues/comments{/number}","contents_url":"https://api.github.com/repos/opesci/devito/contents/{+path}","compare_url":"https://api.github.com/repos/opesci/devito/compare/{base}...{head}","merges_url":"https://api.github.com/repos/opesci/devito/merges","archive_url":"https://api.github.com/repos/opesci/devito/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/opesci/devito/downloads","issues_url":"https://api.github.com/repos/opesci/devito/issues{/number}","pulls_url":"https://api.github.com/repos/opesci/devito/pulls{/number}","milestones_url":"https://api.github.com/repos/opesci/devito/milestones{/number}","notifications_url":"https://api.github.com/repos/opesci/devito/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/opesci/devito/labels{/name}","releases_url":"https://api.github.com/repos/opesci/devito/releases{/id}","deployments_url":"https://api.github.com/repos/opesci/devito/deployments","created_at":"2016-03-23T18:59:49Z","updated_at":"2016-04-22T12:11:36Z","pushed_at":"2016-08-11T11:19:30Z","git_url":"git://github.com/opesci/devito.git","ssh_url":"git@github.com:opesci/devito.git","clone_url":"https://github.com/opesci/devito.git","svn_url":"https://github.com/opesci/devito","homepage":null,"size":1745,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":0,"mirror_url":null,"open_issues_count":17,"forks":0,"open_issues":17,"watchers":0,"default_branch":"master"}},"base":{"label":"opesci:master","ref":"master","sha":"ebef3d1945c1d49be44d75f9f33afa59d86c2d64","user":{"login":"opesci","id":10018551,"avatar_url":"https://avatars.githubusercontent.com/u/10018551?v=3","gravatar_id":"","url":"https://api.github.com/users/opesci","html_url":"https://github.com/opesci","followers_url":"https://api.github.com/users/opesci/followers","following_url":"https://api.github.com/users/opesci/following{/other_user}","gists_url":"https://api.github.com/users/opesci/gists{/gist_id}","starred_url":"https://api.github.com/users/opesci/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/opesci/subscriptions","organizations_url":"https://api.github.com/users/opesci/orgs","repos_url":"https://api.github.com/users/opesci/repos","events_url":"https://api.github.com/users/opesci/events{/privacy}","received_events_url":"https://api.github.com/users/opesci/received_events","type":"Organization","site_admin":false},"repo":{"id":54585666,"name":"devito","full_name":"opesci/devito","owner":{"login":"opesci","id":10018551,"avatar_url":"https://avatars.githubusercontent.com/u/10018551?v=3","gravatar_id":"","url":"https://api.github.com/users/opesci","html_url":"https://github.com/opesci","followers_url":"https://api.github.com/users/opesci/followers","following_url":"https://api.github.com/users/opesci/following{/other_user}","gists_url":"https://api.github.com/users/opesci/gists{/gist_id}","starred_url":"https://api.github.com/users/opesci/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/opesci/subscriptions","organizations_url":"https://api.github.com/users/opesci/orgs","repos_url":"https://api.github.com/users/opesci/repos","events_url":"https://api.github.com/users/opesci/events{/privacy}","received_events_url":"https://api.github.com/users/opesci/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/opesci/devito","description":"Code generation for the inversion workflow","fork":false,"url":"https://api.github.com/repos/opesci/devito","forks_url":"https://api.github.com/repos/opesci/devito/forks","keys_url":"https://api.github.com/repos/opesci/devito/keys{/key_id}","collaborators_url":"https://api.github.com/repos/opesci/devito/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/opesci/devito/teams","hooks_url":"https://api.github.com/repos/opesci/devito/hooks","issue_events_url":"https://api.github.com/repos/opesci/devito/issues/events{/number}","events_url":"https://api.github.com/repos/opesci/devito/events","assignees_url":"https://api.github.com/repos/opesci/devito/assignees{/user}","branches_url":"https://api.github.com/repos/opesci/devito/branches{/branch}","tags_url":"https://api.github.com/repos/opesci/devito/tags","blobs_url":"https://api.github.com/repos/opesci/devito/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/opesci/devito/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/opesci/devito/git/refs{/sha}","trees_url":"https://api.github.com/repos/opesci/devito/git/trees{/sha}","statuses_url":"https://api.github.com/repos/opesci/devito/statuses/{sha}","languages_url":"https://api.github.com/repos/opesci/devito/languages","stargazers_url":"https://api.github.com/repos/opesci/devito/stargazers","contributors_url":"https://api.github.com/repos/opesci/devito/contributors","subscribers_url":"https://api.github.com/repos/opesci/devito/subscribers","subscription_url":"https://api.github.com/repos/opesci/devito/subscription","commits_url":"https://api.github.com/repos/opesci/devito/commits{/sha}","git_commits_url":"https://api.github.com/repos/opesci/devito/git/commits{/sha}","comments_url":"https://api.github.com/repos/opesci/devito/comments{/number}","issue_comment_url":"https://api.github.com/repos/opesci/devito/issues/comments{/number}","contents_url":"https://api.github.com/repos/opesci/devito/contents/{+path}","compare_url":"https://api.github.com/repos/opesci/devito/compare/{base}...{head}","merges_url":"https://api.github.com/repos/opesci/devito/merges","archive_url":"https://api.github.com/repos/opesci/devito/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/opesci/devito/downloads","issues_url":"https://api.github.com/repos/opesci/devito/issues{/number}","pulls_url":"https://api.github.com/repos/opesci/devito/pulls{/number}","milestones_url":"https://api.github.com/repos/opesci/devito/milestones{/number}","notifications_url":"https://api.github.com/repos/opesci/devito/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/opesci/devito/labels{/name}","releases_url":"https://api.github.com/repos/opesci/devito/releases{/id}","deployments_url":"https://api.github.com/repos/opesci/devito/deployments","created_at":"2016-03-23T18:59:49Z","updated_at":"2016-04-22T12:11:36Z","pushed_at":"2016-08-11T11:19:30Z","git_url":"git://github.com/opesci/devito.git","ssh_url":"git@github.com:opesci/devito.git","clone_url":"https://github.com/opesci/devito.git","svn_url":"https://github.com/opesci/devito","homepage":null,"size":1745,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":0,"mirror_url":null,"open_issues_count":17,"forks":0,"open_issues":17,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/opesci/devito/pulls/78"},"html":{"href":"https://github.com/opesci/devito/pull/78"},"issue":{"href":"https://api.github.com/repos/opesci/devito/issues/78"},"comments":{"href":"https://api.github.com/repos/opesci/devito/issues/78/comments"},"review_comments":{"href":"https://api.github.com/repos/opesci/devito/pulls/78/comments"},"review_comment":{"href":"https://api.github.com/repos/opesci/devito/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/opesci/devito/pulls/78/commits"},"statuses":{"href":"https://api.github.com/repos/opesci/devito/statuses/aeeee5c3dc660eabd407a23cd928816261daab8d"}}}}
{"actor":{"display_login":"sheino"}}