{"action":"created","comment":{"url":"https://api.github.com/repos/Theano/Theano/pulls/comments/43309677","id":43309677,"diff_hunk":"@@ -0,0 +1,214 @@\n+.. _extending_op_params:\n+\n+===============\n+Using Op params\n+===============\n+\n+The Op params is a facility to pass some runtime parameters to the\n+code of an op without modifying it.  It can enable a single instance\n+of C code to serve different needs and therefore reduce compilation.\n+\n+The code enables you to pass a single object, but it can be a struct\n+or python object with multiple values if you have more than one value\n+to pass.\n+\n+We will first introduce the parts involved in actually using this\n+functionality and then present a simple working example.\n+\n+The params type\n+----------------\n+\n+You can either reuse an existing type such as :class:`Generic` or\n+create your own.\n+\n+Using a python object for your op parameters (:class:`Generic`) can be\n+annoying to access from C code since you would have to go through the\n+Python-C API for all accesses.\n+\n+Making a purpose-built class may require more upfront work, but can\n+pay off if you reuse the type for a lot of Ops, by not having to re-do\n+all of the python manipulation.\n+\n+\n+Defining a params type\n+~~~~~~~~~~~~~~~~~~~~~~\n+\n+.. note::\n+\n+    This section is only relevant if you decide to create your own type.\n+\n+The first thing you need to do is to define a Theano Type for your\n+params object.  It doesn't have to be complete type because only the\n+following methods will be used for the type:\n+\n+  - :meth:`filter <PureType.filter>`\n+  - :meth:`__eq__ <PureType.__eq__>`\n+  - :meth:`__hash__ <PureType.__hash__>`\n+  - :meth:`values_eq <PureType.values_eq>`\n+\n+Additionaly if you want to use your params with C code, you need the\n+following methods:\n+\n+  - :meth:`c_declare <CLinkerType.c_declare>`\n+  - :meth:`c_init <CLinkerType.c_init>`\n+  - :meth:`c_extract <CLinkerType.c_extract>`\n+  - :meth:`c_cleanup <CLinkerType.c_cleanup>`\n+\n+You can also define other convenience methods such as\n+:meth:`c_headers <CLinkerType.c_headers>` if you need any special things.\n+\n+\n+Registering the params with your Op\n+-----------------------------------\n+\n+To declare that your Op uses params you have to set the class\n+attribute :attr:`params_type` to an instance of your params Type.\n+\n+.. note::\n+\n+   If you want to have multiple parameters you have to bundle those\n+   inside a single object and use that as the params type.\n+\n+For example if we decide to use an int as the params the following\n+would be appropriate:\n+\n+.. code-block:: python\n+\n+   class MyOp(Op):\n+       params_type = Generic()\n+\n+After that you need to define a :meth:`get_params` method on your\n+class with the following signature:\n+\n+.. code-block:: python\n+\n+   def get_params(self, node)\n+\n+This method must return a valid object for your Type (an object that\n+passes :meth:`filter`).  The `node` parameter is the Apply node for\n+which we want the params.  Therefore the params object can depend on\n+the inputs and outputs of the node.\n+\n+.. note::\n+\n+    Due to implementation restrictions, None is not allowed as a\n+    params object and will be taken to mean that the Op doesn't have\n+    parameters.\n+\n+    Since this will change the expected signature of a few methods, it\n+    is strongly discouraged to have your :meth:`get_params` method\n+    return None.\n+\n+\n+Signature changes from having params\n+------------------------------------\n+\n+Having declared a params for your Op will affect the expected\n+signature of :meth:`perform`.  The new expected signature will have an\n+extra parameter at the end which corresponds to the params object.\n+\n+.. warning::\n+\n+   If you do not account for this extra parameter, the code will fail\n+   at runtime if it tries to run the python version.\n+\n+Also, for the C code, the `sub` dictionary will contain an extra entry\n+`'params'` which will map to the variable name of the params object.\n+This is true for all methods that recieve a `sub` parameter, so this\n+means that you can use your params in the :meth:`c_init_code_struct\n+<Op.c_init_code_struct>` method.\n+\n+\n+A simple example\n+----------------\n+\n+This is a simple example which uses a params object to pass a value.\n+This Op will multiply a scalar input by a fixed floating point value.\n+\n+Since the value in this case is a python float, we chose Generic as\n+the params type.\n+\n+.. testcode::\n+\n+   from theano import Op\n+   from theano.gof.type import Generic\n+   from theano.scalar import as_scalar\n+\n+   class MulOp(Op):\n+       params_type = Generic()\n+       __props__ = ('mul',)\n+\n+      def __init__(self, mul):\n+          self.mul = float(mul)\n+\n+      def get_params(self, node):\n+          return self.mul\n+\n+      def make_node(self, inp):\n+          inp = as_scalar(inp)\n+          return Apply(self, [inp], [inp.type()]\n+\n+      def perform(self, node, inputs, output_storage, params):\n+          # Here params is a python float so this is ok\n+          output_storage[0][0] = inputs[0] * params\n+\n+      def c_code(self, node, name, inputs, outputs, sub):\n+          return (\"%(z)s = %(x)s * PyFloat_AsDouble(%(p)s);\" %\n+                  dict(z=outputs[0], x=inputs[0], p=sub['params']))\n+\n+.. testoutput::\n+   :hide:\n+\n+\n+A more complex example\n+----------------------\n+\n+This is a more complex example which actually passes multiple values.  It does a linear combination of two values using floating point weights.\n+\n+.. testcode::\n+\n+   from theano import Op\n+   from theano.gof.type import Generic\n+   from theano.scalar import as_scalar\n+\n+   class ab(object):\n+       def __init__(self, alpha, beta):\n+           self.alpha = alpha\n+           self.beta = beta\n+\n+\n+   class Mix(Op):\n+       params_type = Generic()\n+       __props__ = ('alpha', 'beta')\n+\n+       def __init__(self, alpha, beta):\n+           self.alpha = alpha\n+           self.beta = beta\n+\n+       def get_params(self, node):\n+           return ab(alpha=self.alpha, beta=self.beta)\n+\n+       def make_node(self, x, y):\n+           x = as_scalar(x)\n+           y = as_scalar(y)\n+           return Apply(self, [x, y], [x.type()]\n+\n+       def c_code(self, node, name, inputs, outputs, sub):\n+           return \"\"\"\n+   PyObject *tmp;\n+   double a, b;\n+   tmp = PyObject_GetAttrString(%(p)s, \"alpha\");","path":"doc/extending/using_params.txt","position":200,"original_position":200,"commit_id":"ecf66dd2fbc4c76fd105773efa7b9a59ddd787db","original_commit_id":"ecf66dd2fbc4c76fd105773efa7b9a59ddd787db","user":{"login":"nouiz","id":180987,"avatar_url":"https://avatars.githubusercontent.com/u/180987?v=3","gravatar_id":"","url":"https://api.github.com/users/nouiz","html_url":"https://github.com/nouiz","followers_url":"https://api.github.com/users/nouiz/followers","following_url":"https://api.github.com/users/nouiz/following{/other_user}","gists_url":"https://api.github.com/users/nouiz/gists{/gist_id}","starred_url":"https://api.github.com/users/nouiz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nouiz/subscriptions","organizations_url":"https://api.github.com/users/nouiz/orgs","repos_url":"https://api.github.com/users/nouiz/repos","events_url":"https://api.github.com/users/nouiz/events{/privacy}","received_events_url":"https://api.github.com/users/nouiz/received_events","type":"User","site_admin":false},"body":"Can you move those param access to c_init_code_struct to show this can be done only once to speed up execution?","created_at":"2015-10-28T20:02:38Z","updated_at":"2015-10-28T20:02:38Z","html_url":"https://github.com/Theano/Theano/pull/3562#discussion_r43309677","pull_request_url":"https://api.github.com/repos/Theano/Theano/pulls/3562","_links":{"self":{"href":"https://api.github.com/repos/Theano/Theano/pulls/comments/43309677"},"html":{"href":"https://github.com/Theano/Theano/pull/3562#discussion_r43309677"},"pull_request":{"href":"https://api.github.com/repos/Theano/Theano/pulls/3562"}}},"pull_request":{"url":"https://api.github.com/repos/Theano/Theano/pulls/3562","id":48800874,"html_url":"https://github.com/Theano/Theano/pull/3562","diff_url":"https://github.com/Theano/Theano/pull/3562.diff","patch_url":"https://github.com/Theano/Theano/pull/3562.patch","issue_url":"https://api.github.com/repos/Theano/Theano/issues/3562","number":3562,"state":"open","locked":false,"title":"Small tutorial for op params","user":{"login":"abergeron","id":1002504,"avatar_url":"https://avatars.githubusercontent.com/u/1002504?v=3","gravatar_id":"","url":"https://api.github.com/users/abergeron","html_url":"https://github.com/abergeron","followers_url":"https://api.github.com/users/abergeron/followers","following_url":"https://api.github.com/users/abergeron/following{/other_user}","gists_url":"https://api.github.com/users/abergeron/gists{/gist_id}","starred_url":"https://api.github.com/users/abergeron/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/abergeron/subscriptions","organizations_url":"https://api.github.com/users/abergeron/orgs","repos_url":"https://api.github.com/users/abergeron/repos","events_url":"https://api.github.com/users/abergeron/events{/privacy}","received_events_url":"https://api.github.com/users/abergeron/received_events","type":"User","site_admin":false},"body":"This renames op context to op params and adds a small tutorial for it.\r\n\r\nI felt the rename was warranted beause it's not used much right now and params is a much better name for the new generic usage we are thinking about.\r\n\r\nTesting with a couple of simple multi-gpu programs assures me that the rename went well.","created_at":"2015-10-26T21:37:16Z","updated_at":"2015-10-28T20:02:38Z","closed_at":null,"merged_at":null,"merge_commit_sha":"7739e494666547805ef6a1c8d7e6efba31a8f778","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/Theano/Theano/pulls/3562/commits","review_comments_url":"https://api.github.com/repos/Theano/Theano/pulls/3562/comments","review_comment_url":"https://api.github.com/repos/Theano/Theano/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Theano/Theano/issues/3562/comments","statuses_url":"https://api.github.com/repos/Theano/Theano/statuses/ecf66dd2fbc4c76fd105773efa7b9a59ddd787db","head":{"label":"abergeron:doc_context","ref":"doc_context","sha":"ecf66dd2fbc4c76fd105773efa7b9a59ddd787db","user":{"login":"abergeron","id":1002504,"avatar_url":"https://avatars.githubusercontent.com/u/1002504?v=3","gravatar_id":"","url":"https://api.github.com/users/abergeron","html_url":"https://github.com/abergeron","followers_url":"https://api.github.com/users/abergeron/followers","following_url":"https://api.github.com/users/abergeron/following{/other_user}","gists_url":"https://api.github.com/users/abergeron/gists{/gist_id}","starred_url":"https://api.github.com/users/abergeron/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/abergeron/subscriptions","organizations_url":"https://api.github.com/users/abergeron/orgs","repos_url":"https://api.github.com/users/abergeron/repos","events_url":"https://api.github.com/users/abergeron/events{/privacy}","received_events_url":"https://api.github.com/users/abergeron/received_events","type":"User","site_admin":false},"repo":{"id":2264121,"name":"Theano","full_name":"abergeron/Theano","owner":{"login":"abergeron","id":1002504,"avatar_url":"https://avatars.githubusercontent.com/u/1002504?v=3","gravatar_id":"","url":"https://api.github.com/users/abergeron","html_url":"https://github.com/abergeron","followers_url":"https://api.github.com/users/abergeron/followers","following_url":"https://api.github.com/users/abergeron/following{/other_user}","gists_url":"https://api.github.com/users/abergeron/gists{/gist_id}","starred_url":"https://api.github.com/users/abergeron/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/abergeron/subscriptions","organizations_url":"https://api.github.com/users/abergeron/orgs","repos_url":"https://api.github.com/users/abergeron/repos","events_url":"https://api.github.com/users/abergeron/events{/privacy}","received_events_url":"https://api.github.com/users/abergeron/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/abergeron/Theano","description":"Optimizing GPU-meta-programming code generating array oriented optimizing math compiler in Python","fork":true,"url":"https://api.github.com/repos/abergeron/Theano","forks_url":"https://api.github.com/repos/abergeron/Theano/forks","keys_url":"https://api.github.com/repos/abergeron/Theano/keys{/key_id}","collaborators_url":"https://api.github.com/repos/abergeron/Theano/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/abergeron/Theano/teams","hooks_url":"https://api.github.com/repos/abergeron/Theano/hooks","issue_events_url":"https://api.github.com/repos/abergeron/Theano/issues/events{/number}","events_url":"https://api.github.com/repos/abergeron/Theano/events","assignees_url":"https://api.github.com/repos/abergeron/Theano/assignees{/user}","branches_url":"https://api.github.com/repos/abergeron/Theano/branches{/branch}","tags_url":"https://api.github.com/repos/abergeron/Theano/tags","blobs_url":"https://api.github.com/repos/abergeron/Theano/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/abergeron/Theano/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/abergeron/Theano/git/refs{/sha}","trees_url":"https://api.github.com/repos/abergeron/Theano/git/trees{/sha}","statuses_url":"https://api.github.com/repos/abergeron/Theano/statuses/{sha}","languages_url":"https://api.github.com/repos/abergeron/Theano/languages","stargazers_url":"https://api.github.com/repos/abergeron/Theano/stargazers","contributors_url":"https://api.github.com/repos/abergeron/Theano/contributors","subscribers_url":"https://api.github.com/repos/abergeron/Theano/subscribers","subscription_url":"https://api.github.com/repos/abergeron/Theano/subscription","commits_url":"https://api.github.com/repos/abergeron/Theano/commits{/sha}","git_commits_url":"https://api.github.com/repos/abergeron/Theano/git/commits{/sha}","comments_url":"https://api.github.com/repos/abergeron/Theano/comments{/number}","issue_comment_url":"https://api.github.com/repos/abergeron/Theano/issues/comments{/number}","contents_url":"https://api.github.com/repos/abergeron/Theano/contents/{+path}","compare_url":"https://api.github.com/repos/abergeron/Theano/compare/{base}...{head}","merges_url":"https://api.github.com/repos/abergeron/Theano/merges","archive_url":"https://api.github.com/repos/abergeron/Theano/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/abergeron/Theano/downloads","issues_url":"https://api.github.com/repos/abergeron/Theano/issues{/number}","pulls_url":"https://api.github.com/repos/abergeron/Theano/pulls{/number}","milestones_url":"https://api.github.com/repos/abergeron/Theano/milestones{/number}","notifications_url":"https://api.github.com/repos/abergeron/Theano/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/abergeron/Theano/labels{/name}","releases_url":"https://api.github.com/repos/abergeron/Theano/releases{/id}","created_at":"2011-08-24T20:28:59Z","updated_at":"2015-05-08T20:34:01Z","pushed_at":"2015-10-28T17:52:47Z","git_url":"git://github.com/abergeron/Theano.git","ssh_url":"git@github.com:abergeron/Theano.git","clone_url":"https://github.com/abergeron/Theano.git","svn_url":"https://github.com/abergeron/Theano","homepage":"http://www.deeplearning.net/software/theano","size":47145,"stargazers_count":1,"watchers_count":1,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":0,"forks":1,"open_issues":0,"watchers":1,"default_branch":"master"}},"base":{"label":"Theano:master","ref":"master","sha":"4736c9b3d459a7b0c88bb14c4dd789fe4d09d9b3","user":{"login":"Theano","id":970517,"avatar_url":"https://avatars.githubusercontent.com/u/970517?v=3","gravatar_id":"","url":"https://api.github.com/users/Theano","html_url":"https://github.com/Theano","followers_url":"https://api.github.com/users/Theano/followers","following_url":"https://api.github.com/users/Theano/following{/other_user}","gists_url":"https://api.github.com/users/Theano/gists{/gist_id}","starred_url":"https://api.github.com/users/Theano/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Theano/subscriptions","organizations_url":"https://api.github.com/users/Theano/orgs","repos_url":"https://api.github.com/users/Theano/repos","events_url":"https://api.github.com/users/Theano/events{/privacy}","received_events_url":"https://api.github.com/users/Theano/received_events","type":"Organization","site_admin":false},"repo":{"id":2183193,"name":"Theano","full_name":"Theano/Theano","owner":{"login":"Theano","id":970517,"avatar_url":"https://avatars.githubusercontent.com/u/970517?v=3","gravatar_id":"","url":"https://api.github.com/users/Theano","html_url":"https://github.com/Theano","followers_url":"https://api.github.com/users/Theano/followers","following_url":"https://api.github.com/users/Theano/following{/other_user}","gists_url":"https://api.github.com/users/Theano/gists{/gist_id}","starred_url":"https://api.github.com/users/Theano/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Theano/subscriptions","organizations_url":"https://api.github.com/users/Theano/orgs","repos_url":"https://api.github.com/users/Theano/repos","events_url":"https://api.github.com/users/Theano/events{/privacy}","received_events_url":"https://api.github.com/users/Theano/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Theano/Theano","description":"Theano is a Python library that allows you to define, optimize, and evaluate mathematical expressions involving multi-dimensional arrays efficiently. It can use GPUs and perform efficient symbolic differentiation.","fork":false,"url":"https://api.github.com/repos/Theano/Theano","forks_url":"https://api.github.com/repos/Theano/Theano/forks","keys_url":"https://api.github.com/repos/Theano/Theano/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Theano/Theano/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Theano/Theano/teams","hooks_url":"https://api.github.com/repos/Theano/Theano/hooks","issue_events_url":"https://api.github.com/repos/Theano/Theano/issues/events{/number}","events_url":"https://api.github.com/repos/Theano/Theano/events","assignees_url":"https://api.github.com/repos/Theano/Theano/assignees{/user}","branches_url":"https://api.github.com/repos/Theano/Theano/branches{/branch}","tags_url":"https://api.github.com/repos/Theano/Theano/tags","blobs_url":"https://api.github.com/repos/Theano/Theano/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Theano/Theano/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Theano/Theano/git/refs{/sha}","trees_url":"https://api.github.com/repos/Theano/Theano/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Theano/Theano/statuses/{sha}","languages_url":"https://api.github.com/repos/Theano/Theano/languages","stargazers_url":"https://api.github.com/repos/Theano/Theano/stargazers","contributors_url":"https://api.github.com/repos/Theano/Theano/contributors","subscribers_url":"https://api.github.com/repos/Theano/Theano/subscribers","subscription_url":"https://api.github.com/repos/Theano/Theano/subscription","commits_url":"https://api.github.com/repos/Theano/Theano/commits{/sha}","git_commits_url":"https://api.github.com/repos/Theano/Theano/git/commits{/sha}","comments_url":"https://api.github.com/repos/Theano/Theano/comments{/number}","issue_comment_url":"https://api.github.com/repos/Theano/Theano/issues/comments{/number}","contents_url":"https://api.github.com/repos/Theano/Theano/contents/{+path}","compare_url":"https://api.github.com/repos/Theano/Theano/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Theano/Theano/merges","archive_url":"https://api.github.com/repos/Theano/Theano/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Theano/Theano/downloads","issues_url":"https://api.github.com/repos/Theano/Theano/issues{/number}","pulls_url":"https://api.github.com/repos/Theano/Theano/pulls{/number}","milestones_url":"https://api.github.com/repos/Theano/Theano/milestones{/number}","notifications_url":"https://api.github.com/repos/Theano/Theano/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Theano/Theano/labels{/name}","releases_url":"https://api.github.com/repos/Theano/Theano/releases{/id}","created_at":"2011-08-10T03:48:06Z","updated_at":"2015-10-28T19:46:06Z","pushed_at":"2015-10-28T19:26:28Z","git_url":"git://github.com/Theano/Theano.git","ssh_url":"git@github.com:Theano/Theano.git","clone_url":"https://github.com/Theano/Theano.git","svn_url":"https://github.com/Theano/Theano","homepage":"http://www.deeplearning.net/software/theano","size":70017,"stargazers_count":2191,"watchers_count":2191,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":808,"mirror_url":null,"open_issues_count":509,"forks":808,"open_issues":509,"watchers":2191,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/Theano/Theano/pulls/3562"},"html":{"href":"https://github.com/Theano/Theano/pull/3562"},"issue":{"href":"https://api.github.com/repos/Theano/Theano/issues/3562"},"comments":{"href":"https://api.github.com/repos/Theano/Theano/issues/3562/comments"},"review_comments":{"href":"https://api.github.com/repos/Theano/Theano/pulls/3562/comments"},"review_comment":{"href":"https://api.github.com/repos/Theano/Theano/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Theano/Theano/pulls/3562/commits"},"statuses":{"href":"https://api.github.com/repos/Theano/Theano/statuses/ecf66dd2fbc4c76fd105773efa7b9a59ddd787db"}}}}