{"action":"opened","issue":{"url":"https://api.github.com/repos/akualab/narray/issues/1","labels_url":"https://api.github.com/repos/akualab/narray/issues/1/labels{/name}","comments_url":"https://api.github.com/repos/akualab/narray/issues/1/comments","events_url":"https://api.github.com/repos/akualab/narray/issues/1/events","html_url":"https://github.com/akualab/narray/issues/1","id":63205711,"number":1,"title":"Generate assembly for common functions","user":{"login":"klauspost","id":5663952,"avatar_url":"https://avatars.githubusercontent.com/u/5663952?v=3","gravatar_id":"","url":"https://api.github.com/users/klauspost","html_url":"https://github.com/klauspost","followers_url":"https://api.github.com/users/klauspost/followers","following_url":"https://api.github.com/users/klauspost/following{/other_user}","gists_url":"https://api.github.com/users/klauspost/gists{/gist_id}","starred_url":"https://api.github.com/users/klauspost/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/klauspost/subscriptions","organizations_url":"https://api.github.com/users/klauspost/orgs","repos_url":"https://api.github.com/users/klauspost/repos","events_url":"https://api.github.com/users/klauspost/events{/privacy}","received_events_url":"https://api.github.com/users/klauspost/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":0,"created_at":"2015-03-20T10:30:43Z","updated_at":"2015-03-20T10:30:43Z","closed_at":null,"body":"I don't know if it was always the plan, but the current library makes it very easy to create assembler optimized routines.\r\n\r\nHere is an example of how it could be structured:\r\n\r\n```Go\r\n// Div divides two narrays elementwise.\r\n// out = in0 / in1\r\n// If out is nil a new array is created.\r\nfunc Div(out *NArray, in0, in1 *NArray) *NArray {\r\n\r\n\tif out == nil {\r\n\t\tout = New(in0.Shape...)\r\n\t}\r\n\tif !EqualShape(out, in0, in1) {\r\n\t\tpanic(\"narrays must have equal shape.\")\r\n\t}\r\n\tdivSlice(out.Data, in0.Data, in1.Data)\r\n\treturn out\r\n}\r\n\r\n// Generic function, this is quite easy to do in SSE2 for instance.\r\n// Assumptions the assembly can make:\r\n// out != nil, a != nil, b != nil\r\n// len(out)  == len(a) == len(b)\r\nfunc divSlice(out, a, b []float64) {\r\n\tfor i := 0; i < len(out.Data); i++ {\r\n\t\tout[i] = a[i] / b[i]\r\n\t}\r\n}\r\n```\r\nThe `divSlice` function can then be assembler, which can eliminate bounds-checks, and even do multiple elements in parallel, something like this:\r\n\r\n```Go\r\nfunc divSlice(out, a, b []float64) {\r\n\tl := len(out)\r\n\tl2 := l / 2\r\n\tfor i := 0; i < l2; i++ {\r\n                // This is of course a single instruction on SSE2\r\n\t\tout[i*2] = a[i*2] / b[i*2]\r\n\t\tout[i*2+1] = a[i*2+1] / b[i*2+1]\r\n\t}\r\n\tif l&1 == 1 {\r\n\t\tout[l-1] = a[l-1] / b[l-1]\r\n\t}\r\n}\r\n```\r\n\r\nIf I am not completely mistaking, this should make these types of operations at least an order of magnitude faster for decently sized arrays.\r\n\r\nIs this something you are looking into, or should I dig further into this myself?"}}