{"action":"opened","issue":{"url":"https://api.github.com/repos/oscar-system/GAPJulia/issues/68","repository_url":"https://api.github.com/repos/oscar-system/GAPJulia","labels_url":"https://api.github.com/repos/oscar-system/GAPJulia/issues/68/labels{/name}","comments_url":"https://api.github.com/repos/oscar-system/GAPJulia/issues/68/comments","events_url":"https://api.github.com/repos/oscar-system/GAPJulia/issues/68/events","html_url":"https://github.com/oscar-system/GAPJulia/issues/68","id":369085599,"node_id":"MDU6SXNzdWUzNjkwODU1OTk=","number":68,"title":"Benchmark and optimize calls from Julia to GAP functions","user":{"login":"fingolfin","id":241512,"node_id":"MDQ6VXNlcjI0MTUxMg==","avatar_url":"https://avatars2.githubusercontent.com/u/241512?v=4","gravatar_id":"","url":"https://api.github.com/users/fingolfin","html_url":"https://github.com/fingolfin","followers_url":"https://api.github.com/users/fingolfin/followers","following_url":"https://api.github.com/users/fingolfin/following{/other_user}","gists_url":"https://api.github.com/users/fingolfin/gists{/gist_id}","starred_url":"https://api.github.com/users/fingolfin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fingolfin/subscriptions","organizations_url":"https://api.github.com/users/fingolfin/orgs","repos_url":"https://api.github.com/users/fingolfin/repos","events_url":"https://api.github.com/users/fingolfin/events{/privacy}","received_events_url":"https://api.github.com/users/fingolfin/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2018-10-11T11:55:52Z","updated_at":"2018-10-11T11:55:52Z","closed_at":null,"author_association":"MEMBER","body":"Now that calls from GAP to Julia have been improved a lot, the same should be done for the other way around.\r\n\r\nRight now, GAP function calls from Julia are handled via this function:\r\n```julia\r\nfunction(func::GapFunc)(args...)\r\n    arg_array = collect(args)\r\n    result = ccall(Main.gap_call_gap_func,Any,\r\n                        (MPtr,Any),func.ptr, arg_array )\r\n    return result\r\nend\r\n```\r\nAnd then `call_gap_func` is defined like this:\r\n```C\r\njl_value_t * call_gap_func(void * func, jl_value_t * arg_array)\r\n{\r\n    jl_array_t * array_ptr = (jl_array_t *)arg_array;\r\n    size_t       len = jl_array_len(array_ptr);\r\n    Obj          arg_list = NEW_PLIST(T_PLIST, len);\r\n    SET_LEN_PLIST(arg_list, len);\r\n    for (size_t i = 0; i < len; i++) {\r\n        SET_ELM_PLIST(arg_list, i + 1, gap_julia(jl_arrayref(array_ptr, i)));\r\n        CHANGED_BAG(arg_list);\r\n    }\r\n    Obj return_val = CallFuncList((Obj)(func), arg_list);\r\n    if (return_val == NULL) {\r\n        return jl_nothing;\r\n    }\r\n    return julia_gap(return_val);\r\n}\r\n```\r\n\r\nNote that this always creates a plist, even if there is no argument, or only a few. Then the GAP kernel function `CallFuncList` in most cases (for <= 6 arguments) will extract the entries of this plist (and effectively discard the plist afterwards, in that it won't be referenced anymore afterwars), and the invoke optimized function dispatches for 0 to 6 arguments.\r\n\r\nMy guess is that we can get a measurable speedup by providing multiple function call handlers on the Julia side, namely for 0 to 6 arguments, and the current one is retained for calls with more arguments. This then of course needs to be matched on the GAP side (in the JuliaInterface kernel extension) with (probably rather simple) call handlers.\r\n\r\nHowever, I strongly suggest to create some benchmarks first, like I did for calls the other way around, to see whether this has the desired effect of improving performance (and reducing memory pressure, by allocating fewer temporary plists). "}}
{"actor":{"display_login":"fingolfin"}}