{"action":"created","issue":{"url":"https://api.github.com/repos/JOML-CI/JOML/issues/81","repository_url":"https://api.github.com/repos/JOML-CI/JOML","labels_url":"https://api.github.com/repos/JOML-CI/JOML/issues/81/labels{/name}","comments_url":"https://api.github.com/repos/JOML-CI/JOML/issues/81/comments","events_url":"https://api.github.com/repos/JOML-CI/JOML/issues/81/events","html_url":"https://github.com/JOML-CI/JOML/issues/81","id":152044905,"number":81,"title":"Provide SSE-optimized JNI functions","user":{"login":"httpdigest","id":7488613,"avatar_url":"https://avatars.githubusercontent.com/u/7488613?v=3","gravatar_id":"","url":"https://api.github.com/users/httpdigest","html_url":"https://github.com/httpdigest","followers_url":"https://api.github.com/users/httpdigest/followers","following_url":"https://api.github.com/users/httpdigest/following{/other_user}","gists_url":"https://api.github.com/users/httpdigest/gists{/gist_id}","starred_url":"https://api.github.com/users/httpdigest/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/httpdigest/subscriptions","organizations_url":"https://api.github.com/users/httpdigest/orgs","repos_url":"https://api.github.com/users/httpdigest/repos","events_url":"https://api.github.com/users/httpdigest/events{/privacy}","received_events_url":"https://api.github.com/users/httpdigest/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/JOML-CI/JOML/labels/enhancement","name":"enhancement","color":"84b6eb"}],"state":"open","locked":false,"assignee":{"login":"httpdigest","id":7488613,"avatar_url":"https://avatars.githubusercontent.com/u/7488613?v=3","gravatar_id":"","url":"https://api.github.com/users/httpdigest","html_url":"https://github.com/httpdigest","followers_url":"https://api.github.com/users/httpdigest/followers","following_url":"https://api.github.com/users/httpdigest/following{/other_user}","gists_url":"https://api.github.com/users/httpdigest/gists{/gist_id}","starred_url":"https://api.github.com/users/httpdigest/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/httpdigest/subscriptions","organizations_url":"https://api.github.com/users/httpdigest/orgs","repos_url":"https://api.github.com/users/httpdigest/repos","events_url":"https://api.github.com/users/httpdigest/events{/privacy}","received_events_url":"https://api.github.com/users/httpdigest/received_events","type":"User","site_admin":false},"milestone":null,"comments":2,"created_at":"2016-04-30T18:24:19Z","updated_at":"2016-05-09T17:15:36Z","closed_at":null,"body":"Previously, I did some testing on doing matrix calculations in native functions via SSE/AVX instructions: https://github.com/JOML-CI/JOML/issues/30\r\n\r\nThat turned out to be slower than the calculations with standard scalar arithmetic operations in Java. This was due to the approach of \"batching\" all operations. In order for that batching to work, the operands to each method invocations as well as the opcodes of each operation had to be stored in native memory for the native function to decode/read and execute. That storing and reading of the opcodes and operands was the major bottleneck.\r\n\r\nNow, there is another more promising approach: Not batching the operations but simply directly calling a JNI function to do the job with optimized SSE instructions. Initial testing showed major performance increases. See the JMH results below:\r\n\r\n```\r\njoml-array (using a float[16]):\r\n\r\nBenchmark                             Mode  Cnt          Score         Error  Units\r\nMatrix4fBenchmarks.testInvert        thrpt    3   24760865,260 ±  910609,284  ops/s\r\nMatrix4fBenchmarks.testMul           thrpt    3   34555251,163 ±  183270,652  ops/s\r\nMatrix4fBenchmarks.testMulAffine     thrpt    3   52189265,415 ±  622020,725  ops/s\r\n\r\njoml-jni (using native memory and JNI functions):\r\n\r\nBenchmark                             Mode  Cnt          Score          Error  Units\r\nMatrix4fBenchmarks.testInvert        thrpt    3   36367075,182 ±   283999,981  ops/s\r\nMatrix4fBenchmarks.testMul           thrpt    3   70239126,361 ±    27891,033  ops/s\r\nMatrix4fBenchmarks.testMulAffine     thrpt    3   76090662,949 ±   342632,179  ops/s\r\n```\r\n\r\nWork on intrinsifying all heavy/important JOML methods has started in the [jni](https://github.com/JOML-CI/JOML/tree/jni) branch based off the [array](https://github.com/JOML-CI/JOML/tree/array) branch."},"comment":{"url":"https://api.github.com/repos/JOML-CI/JOML/issues/comments/217928020","html_url":"https://github.com/JOML-CI/JOML/issues/81#issuecomment-217928020","issue_url":"https://api.github.com/repos/JOML-CI/JOML/issues/81","id":217928020,"user":{"login":"httpdigest","id":7488613,"avatar_url":"https://avatars.githubusercontent.com/u/7488613?v=3","gravatar_id":"","url":"https://api.github.com/users/httpdigest","html_url":"https://github.com/httpdigest","followers_url":"https://api.github.com/users/httpdigest/followers","following_url":"https://api.github.com/users/httpdigest/following{/other_user}","gists_url":"https://api.github.com/users/httpdigest/gists{/gist_id}","starred_url":"https://api.github.com/users/httpdigest/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/httpdigest/subscriptions","organizations_url":"https://api.github.com/users/httpdigest/orgs","repos_url":"https://api.github.com/users/httpdigest/repos","events_url":"https://api.github.com/users/httpdigest/events{/privacy}","received_events_url":"https://api.github.com/users/httpdigest/received_events","type":"User","site_admin":false},"created_at":"2016-05-09T17:15:36Z","updated_at":"2016-05-09T17:15:36Z","body":"Here are some benchmark results on an i7 with JDK1.8.0_92:\r\n```\r\nBenchmark                            Mode  Cnt   Score   Error  Units\r\nMatrix4fBenchmarks.CopyPojo          avgt    5   8,356 ± 0,741  ns/op\r\nMatrix4fBenchmarks.CopyUnsafe        avgt    5   7,326 ± 0,605  ns/op\r\nMatrix4fBenchmarks.IdentityPojo      avgt    5   6,138 ± 0,840  ns/op\r\nMatrix4fBenchmarks.IdentityUnsafe    avgt    5   5,637 ± 0,613  ns/op\r\nMatrix4fBenchmarks.InvertAVX         avgt    5  22,756 ± 3,017  ns/op\r\nMatrix4fBenchmarks.InvertAffinePojo  avgt    5  22,754 ± 1,666  ns/op\r\nMatrix4fBenchmarks.InvertPojo        avgt    5  40,903 ± 9,051  ns/op\r\nMatrix4fBenchmarks.InvertSSE         avgt    5  25,583 ± 5,732  ns/op\r\nMatrix4fBenchmarks.MulAVX            avgt    5  15,027 ± 1,642  ns/op\r\nMatrix4fBenchmarks.MulAffineAVX      avgt    5  11,220 ± 0,655  ns/op\r\nMatrix4fBenchmarks.MulAffinePojo     avgt    5  16,367 ± 1,103  ns/op\r\nMatrix4fBenchmarks.MulPojo           avgt    5  25,561 ± 2,351  ns/op\r\nMatrix4fBenchmarks.MulSSE            avgt    5  14,497 ± 0,352  ns/op\r\nMatrix4fBenchmarks.ZeroPojo          avgt    5   6,322 ± 0,655  ns/op\r\nMatrix4fBenchmarks.ZeroUnsafe        avgt    5   5,185 ± 0,741  ns/op\r\n```\r\nPOJO means the normal Matrix4f Java version with the 16 primitive float fields, Unsafe means that there was `sun.misc.Unsafe` used for faster copying, SSE means JNI function using x86 SSE-128bit, AVX means JNI function using x86 AVX1-128bit."}}