{"action":"created","comment":{"url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/pulls/comments/229799954","pull_request_review_id":170379271,"id":229799954,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIyOTc5OTk1NA==","diff_hunk":"@@ -0,0 +1,271 @@\n+Bye bye boost.simd, welcome xsimd\n+#################################\n+\n+:date: 2018-10-31\n+:category: engineering\n+:lang: en\n+:authors: serge-sans-paille\n+:summary: After five years of friendship, Pythran replaces ``boost.simd`` by\n+          ``xsimd`` as its vectorization engine. This post goes through the\n+          motivation of this change, and the advantage of this move.\n+\n+`boost.simd <https://github.com/NumScale/boost.simd>`_ provides a C++\n+abstraction of vector type, allowing for efficient vectorization of array\n+computations. It has been (optionally) used as part of the expression template\n+engine of Pythran for a long time, a great collaboration that led to several\n+patch in boost.simd, and great performance for Pythran.\n+\n+Unfortunately, the project has been silent over the last months (see for\n+instance `this issue <https://github.com/NumScale/boost.simd/issues/546>`_ and\n+I had to maintain a few custom patches. Turns out the project has been\n+re-branded as **bSIMD** with a more restrictive license, as detailed in `another\n+issue <https://github.com/NumScale/boost.simd/issues/545>`_. From the Pythran\n+perspective, this is no good news.\n+\n+Fortunately, the people from `QuantStack <http://quantstack.net/>`_ have put\n+tremendous effort into providing an equivalent to boost.simd, *xsimd*. And\n+their library actually provides some improvements in the context of Pythran, so\n+when they proposed to fund the move to *xsimd*, it was just perfect.\n+\n+So here is the deal: I do the port, report any API and/or performance issue,\n+and eventually provide patch when relevant. That's what I did over the last\n+three months, let's have a look at the result.\n+\n+User-level Changes\n+==================\n+\n+In order to activate explicit vectorisation, one must pass ``-DUSE_XSIMD -march=native`` to the pythran compiler, in place of ``-DUSE_BOOST_SIMD -march=native``. Fair enough.\n+\n+For instance, consider the following kernel, taken from the `numpy benchmarks\n+suite <https://github.com/serge-sans-paille/numpy-benchmarks/>`_ suite I\n+maintain.\n+\n+.. code-block:: python\n+\n+    #pythran export arc_distance(float64 [], float64[], float64[], float64[])\n+\n+    import numpy as np\n+    def arc_distance(theta_1, phi_1,\n+                           theta_2, phi_2):\n+        \"\"\"\n+        Calculates the pairwise arc distance between all points in vector a and b.\n+        \"\"\"\n+        temp = np.sin((theta_2-theta_1)/2)**2+np.cos(theta_1)*np.cos(theta_2)*np.sin((phi_2-phi_1)/2)**2\n+        distance_matrix = 2 * (np.arctan2(np.sqrt(temp),np.sqrt(1-temp)))\n+        return distance_matrix\n+\n+When compiled with GCC 7.3 and benchmarked with the `perf <https://pypi.org/project/perf/>`_ module, one gets\n+\n+.. code-block:: sh\n+\n+    CC=clang CXX=clang++ pythran arc_distance.py -O3 -march=native\n+    python -m perf timeit -s 'N = 10000 ; import numpy as np ; np.random.seed(0); t0, p0, t1, p1 = np.random.randn(N), np.random.randn(N), np.random.randn(N), np.random.randn(N); from arc_distance import arc_distance' 'arc_distance(t0, p0, t1, p1)'\n+    .....................\n+    Mean +- std dev: 1.48 ms +- 0.01 ms\n+\n+That's our base line. If we recompile it with ``-DUSE_XSIMD``, we get an extra speedup (AVX instructions are available on my laptop, and enabled by ``-march=native``).\n+\n+.. code-block:: sh\n+\n+    CC=clang CXX=clang++ python -m pythran.run arc_distance.py -O3 -march=native -DUSE_XSIMD\n+    python -m perf timeit -s 'N = 10000 ; import numpy as np ; np.random.seed(0); t0, p0, t1, p1 = np.random.randn(N), np.random.randn(N), np.random.randn(N), np.random.randn(N); from arc_distance import arc_distance' 'arc_distance(t0, p0, t1, p1)'\n+    .....................\n+    Mean +- std dev: 199 us +- 4 us\n+\n+That's roughly 7 times faster. And using Pythran 0.8.7, the last release with boost.simd support, we have\n+\n+.. code-block:: sh\n+\n+    CC=clang CXX=clang++ python -m pythran.run arc_distance.py -O3 -march=native -DUSE_BOOST_SIMD\n+    python -m perf timeit -s 'N = 10000 ; import numpy as np ; np.random.seed(0); t0, p0, t1, p1 = np.random.randn(N), np.random.randn(N), np.random.randn(N), np.random.randn(N); from arc_distance import arc_distance' 'arc_distance(t0, p0, t1, p1)'\n+    .....................\n+    Mean +- std dev: 284 us +- 8 us\n+\n+This is slightly slower, but within the same magnitude order. Out of curiosity, I ran the same three experiments using Clang 6 as a backend compiler and I get the following timings:\n+\n+.. code::\n+\n+    clang + boost.simd: 220 us +- 8 us\n+    clang + xsimd:      273 us +- 11 us\n+    clang:             1.41 ms +- 0.04 ms\n+\n+Interestingly, **on that example**, Clang generates better code for the boost.simd version. So let's be wary of hasty conclusion and just state that with both engines, I can get efficient vectorization of my code.\n+\n+Complex Numbers\n+===============\n+\n+Thanks to xsimd, Pythran is no able to *naively* support complex number\n+vectorization. I state *naively* because we don't support changing internal\n+representation from array-of-struct to struct-of-array, as we stick to numpy's\n+layout. Still that's something new for Pythran as showcased by the following kernel:\n+\n+.. code-block:: python\n+\n+    #pythran export normalize_complex_arr(complex[])\n+\n+    import numpy as np\n+    def normalize_complex_arr(a):\n+        a_oo = a - a.real.min() - 1j*a.imag.min() # origin offsetted\n+        return a_oo/np.abs(a_oo).max()\n+\n+\n+Pythran provides a vectorized version of ``np.min`` and ``np.max`` operators, so thanks to complex support, it should provide some decent acceleration. Let's check that!\n+\n+.. code-block:: sh\n+\n+    CC=gcc CXX=g++ pythran -march=native -O3 normalize_complex_arr.py\n+    python -m perf timeit -s 'import numpy as np; np.random.seed(0); N = 100000; x = np.random.random(N) + 1j *  np.random.random(N); from normalize_complex_arr import normalize_complex_arr' 'normalize_complex_arr(x)'\n+    .....................\n+    Mean +- std dev: 2.84 ms +- 0.01 ms\n+\n+\n+And with vectorization on (note that the calls to ``np.min()`` do not involve complex numbers though.\n+\n+.. code-block:: sh\n+\n+    CC=gcc CXX=g++ pythran -march=native -O3 make_decision.py -DUSE_XSIMD\n+    python -m perf timeit -s 'import numpy as np; np.random.seed(0); N = 100000; x = np.random.random(N) + 1j *  np.random.random(N); from normalize_complex_arr import normalize_complex_arr' 'normalize_complex_arr(x)'\n+    .....................\n+    Mean +- std dev: 723 us +- 14 us\n+\n+Cool! Speedup for complex! For the record, the numpy version already ran at roughly ``3.19 ms +- 0.02 ms``.\n+\n+Scalar Version\n+==============\n+\n+That's probably a detail for many xsimd users, but thanks to this cooperation,\n+xsimd now exposes a scalar version of all its mathematical function inside the\n+``xsimd::`` namespace. That way one can write higher level functions based on\n+xsimd, and they would work for both scalar and vector version:\n+\n+.. code-block:: c++\n+\n+    template<class T>\n+    T euclidian_distance_squared(T x, T y)\n+    {\n+        auto tmp = xsimd::hypot(x, y);\n+        return tmp * tmp;\n+    }\n+\n+In the context of Pythran, this makes the expression template engine easier to\n+write. Good point.\n+\n+\n+Compilation Time\n+================\n+\n+Pythran is an *Ahead of Time* compiler, so compilation time is generally not a\n+good metric. But there's one situation where it matters to me: Continuous\n+Integration. Because Travis has time limits, the faster we compile, the more\n+test we can pass! As Pythran validates for Python2 and Python3, for Clang and\n+GCC, with and without SIMD, with and without OpenMP, that's a lot of\n+configuration to test. Roughly... 20hours of cumulated tests actually, see\n+`this recent build\n+<https://travis-ci.com/serge-sans-paille/pythran/builds/89663340>`_ for\n+instance.\n+\n+In pre-xsimd setting, compiling the above  ``arc_distance.py`` file in simd mode is relatively slow:\n+\n+.. code-block:: sh\n+\n+    time pythran -O3 -march=native normalize_complex_arr.py -E # generate the .cpp\n+    0.91s user 0.28s system 130% cpu 0.908 total\n+    time pythran -O3 -march=native normalize_complex_arr.cpp -DUSE_BOOST_SIMD\n+    12.10s user 0.79s system 102% cpu 12.616 total\n+\n+\n+With xsimd, it's slightly faster (no boost dependencies, and less C++ magic).\n+\n+.. code-block:: sh\n+\n+    time pythran -O3 -march=native arc_distance.cpp -DUSE_XSIMD\n+    10.32s user 0.65s system 102% cpu 10.688 total\n+\n+Arguably, it's still slow. But a bit less then what it uses to be, and the reason also lies in the generated c++, not only in the vectorization engine:\n+\n+.. code-block:: sh\n+\n+    time pythran -O3 -march=native arc_distance.cpp\n+    5.67s user 0.61s system 104% cpu 6.001 total\n+\n+\n+Performance of Basic Functions\n+==============================\n+\n+Using `airspeed velocity <https://github.com/airspeed-velocity/asv>`_, I've compared how well xsimd behaves for simple operations on 1D array. All the benchmarks hereafter have the following form:\n+\n+.. code-block:: python\n+\n+    #pythran export cos_array(float64 [])\n+    #setup: import numpy as np ; np.random.seed(0); N = 10000 ; x = np.random.random(N) * 2 * np.pi\n+    #run: cos_array(x)\n+    import numpy as np\n+    def cos_array(x):\n+        return np.cos(x)\n+\n+\n+The results are obtained through the ``asv compare commit_id0 commit_id1`` command.\n+\n+.. code::\n+\n+    All benchmarks:\n+\n+        before     after       ratio\n+      [99d8234f] [60632651]\n+         9.90μs     9.89μs      1.00  benchmarks.TimeSuite.time_abs_array\n+    +   36.82μs    58.44μs      1.59  benchmarks.TimeSuite.time_acos_array\n+        36.25μs    33.60μs      0.93  benchmarks.TimeSuite.time_asin_array\n+    -   50.47μs    33.03μs      0.65  benchmarks.TimeSuite.time_atan_array\n+    -   48.62μs    35.72μs      0.73  benchmarks.TimeSuite.time_cos_array\n+    -   73.82μs    43.81μs      0.59  benchmarks.TimeSuite.time_cosh_array\n+    -   47.55μs    35.52μs      0.75  benchmarks.TimeSuite.time_sin_array\n+    -   91.45μs    47.86μs      0.52  benchmarks.TimeSuite.time_sinh_array\n+        18.35μs    17.91μs      0.98  benchmarks.TimeSuite.time_sqrt_array\n+         9.60μs    10.05μs      1.05  benchmarks.TimeSuite.time_square_array\n+    -   71.71μs    33.35μs      0.47  benchmarks.TimeSuite.time_tan_array\n+    -   84.63μs    42.28μs      0.50  benchmarks.TimeSuite.time_tanh_array\n+\n+Looks pretty good! Apart from a regression on ``acos``, this is either on-par or faster than before.\n+\n+Out of curiosity, I also ran the same benchmark, but using Clang as back-end.\n+\n+.. code::\n+\n+    All benchmarks:\n+\n+        before     after       ratio\n+      [99d8234f] [60632651]\n+         9.57μs    10.00μs      1.05  benchmarks.TimeSuite.time_abs_array\n+    +   34.20μs    58.53μs      1.71  benchmarks.TimeSuite.time_acos_array\n+        36.09μs    33.91μs      0.94  benchmarks.TimeSuite.time_asin_array\n+    -   45.02μs    33.86μs      0.75  benchmarks.TimeSuite.time_atan_array\n+    +   39.44μs    45.48μs      1.15  benchmarks.TimeSuite.time_cos_array\n+    -   65.98μs    44.78μs      0.68  benchmarks.TimeSuite.time_cosh_array\n+    +   39.39μs    45.48μs      1.15  benchmarks.TimeSuite.time_sin_array\n+    -  110.62μs    48.44μs      0.44  benchmarks.TimeSuite.time_sinh_array\n+        18.18μs    18.54μs      1.02  benchmarks.TimeSuite.time_sqrt_array\n+        10.05μs     9.56μs      0.95  benchmarks.TimeSuite.time_square_array\n+    -   56.82μs    45.32μs      0.80  benchmarks.TimeSuite.time_tan_array\n+    -   98.85μs    44.16μs      0.45  benchmarks.TimeSuite.time_tanh_array\n+\n+Wow, that's significant changes. Regression on both ``cos``, ``sin`` and ``acos`` are not good news.\n+\n+What conclusion should we draw? My take on this is that these benchmarks are\n+not synthetic enough to state *xsimd implementation of function X is better or\n+worse than boost.simd implementation*. But maybe there are bad interactions\n+with Pythran's expression template? A single register spill could wreak havoc\n+in the performance, and I know there is room for improvement there.\n+\n+Conclusions\n+===========\n+\n+I'm indeed very happy with the changes. The xsimd team is very reactive, it's\n+cool to chat with them about performance, Python, C++... And did I see xsimd\n+supports Neon, avx512? I should try to run cross-compiled Pythran code on a\n+Raspberry, but... That's for another story!\n+\n+Again thanks a lot to (alphabetical order) `Johan\n+<https://twitter.com/JohanMabille>`_, `martin","path":"content/2018-10-31-xsimd.rst","position":268,"original_position":268,"commit_id":"8c90afed5d8d12045335b1a222affa6d07c9fefd","original_commit_id":"8c90afed5d8d12045335b1a222affa6d07c9fefd","user":{"login":"HadrienG2","id":1305080,"node_id":"MDQ6VXNlcjEzMDUwODA=","avatar_url":"https://avatars1.githubusercontent.com/u/1305080?v=4","gravatar_id":"","url":"https://api.github.com/users/HadrienG2","html_url":"https://github.com/HadrienG2","followers_url":"https://api.github.com/users/HadrienG2/followers","following_url":"https://api.github.com/users/HadrienG2/following{/other_user}","gists_url":"https://api.github.com/users/HadrienG2/gists{/gist_id}","starred_url":"https://api.github.com/users/HadrienG2/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/HadrienG2/subscriptions","organizations_url":"https://api.github.com/users/HadrienG2/orgs","repos_url":"https://api.github.com/users/HadrienG2/repos","events_url":"https://api.github.com/users/HadrienG2/events{/privacy}","received_events_url":"https://api.github.com/users/HadrienG2/received_events","type":"User","site_admin":false},"body":"Martin?","created_at":"2018-10-31T17:43:12Z","updated_at":"2018-10-31T17:55:24Z","html_url":"https://github.com/serge-sans-paille/pythran-stories/pull/15#discussion_r229799954","pull_request_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/pulls/15","author_association":"NONE","_links":{"self":{"href":"https://api.github.com/repos/serge-sans-paille/pythran-stories/pulls/comments/229799954"},"html":{"href":"https://github.com/serge-sans-paille/pythran-stories/pull/15#discussion_r229799954"},"pull_request":{"href":"https://api.github.com/repos/serge-sans-paille/pythran-stories/pulls/15"}}},"pull_request":{"url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/pulls/15","id":227372042,"node_id":"MDExOlB1bGxSZXF1ZXN0MjI3MzcyMDQy","html_url":"https://github.com/serge-sans-paille/pythran-stories/pull/15","diff_url":"https://github.com/serge-sans-paille/pythran-stories/pull/15.diff","patch_url":"https://github.com/serge-sans-paille/pythran-stories/pull/15.patch","issue_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/issues/15","number":15,"state":"open","locked":false,"title":"Draft/xsimd","user":{"login":"serge-sans-paille","id":863807,"node_id":"MDQ6VXNlcjg2MzgwNw==","avatar_url":"https://avatars1.githubusercontent.com/u/863807?v=4","gravatar_id":"","url":"https://api.github.com/users/serge-sans-paille","html_url":"https://github.com/serge-sans-paille","followers_url":"https://api.github.com/users/serge-sans-paille/followers","following_url":"https://api.github.com/users/serge-sans-paille/following{/other_user}","gists_url":"https://api.github.com/users/serge-sans-paille/gists{/gist_id}","starred_url":"https://api.github.com/users/serge-sans-paille/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/serge-sans-paille/subscriptions","organizations_url":"https://api.github.com/users/serge-sans-paille/orgs","repos_url":"https://api.github.com/users/serge-sans-paille/repos","events_url":"https://api.github.com/users/serge-sans-paille/events{/privacy}","received_events_url":"https://api.github.com/users/serge-sans-paille/received_events","type":"User","site_admin":false},"body":"","created_at":"2018-10-31T17:13:19Z","updated_at":"2018-10-31T17:55:24Z","closed_at":null,"merged_at":null,"merge_commit_sha":"95970a0b04a4571ff2023d7d5de88fe1458b1067","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/pulls/15/commits","review_comments_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/pulls/15/comments","review_comment_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/pulls/comments{/number}","comments_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/issues/15/comments","statuses_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/statuses/8c90afed5d8d12045335b1a222affa6d07c9fefd","head":{"label":"serge-sans-paille:draft/xsimd","ref":"draft/xsimd","sha":"8c90afed5d8d12045335b1a222affa6d07c9fefd","user":{"login":"serge-sans-paille","id":863807,"node_id":"MDQ6VXNlcjg2MzgwNw==","avatar_url":"https://avatars1.githubusercontent.com/u/863807?v=4","gravatar_id":"","url":"https://api.github.com/users/serge-sans-paille","html_url":"https://github.com/serge-sans-paille","followers_url":"https://api.github.com/users/serge-sans-paille/followers","following_url":"https://api.github.com/users/serge-sans-paille/following{/other_user}","gists_url":"https://api.github.com/users/serge-sans-paille/gists{/gist_id}","starred_url":"https://api.github.com/users/serge-sans-paille/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/serge-sans-paille/subscriptions","organizations_url":"https://api.github.com/users/serge-sans-paille/orgs","repos_url":"https://api.github.com/users/serge-sans-paille/repos","events_url":"https://api.github.com/users/serge-sans-paille/events{/privacy}","received_events_url":"https://api.github.com/users/serge-sans-paille/received_events","type":"User","site_admin":false},"repo":{"id":53442021,"node_id":"MDEwOlJlcG9zaXRvcnk1MzQ0MjAyMQ==","name":"pythran-stories","full_name":"serge-sans-paille/pythran-stories","private":false,"owner":{"login":"serge-sans-paille","id":863807,"node_id":"MDQ6VXNlcjg2MzgwNw==","avatar_url":"https://avatars1.githubusercontent.com/u/863807?v=4","gravatar_id":"","url":"https://api.github.com/users/serge-sans-paille","html_url":"https://github.com/serge-sans-paille","followers_url":"https://api.github.com/users/serge-sans-paille/followers","following_url":"https://api.github.com/users/serge-sans-paille/following{/other_user}","gists_url":"https://api.github.com/users/serge-sans-paille/gists{/gist_id}","starred_url":"https://api.github.com/users/serge-sans-paille/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/serge-sans-paille/subscriptions","organizations_url":"https://api.github.com/users/serge-sans-paille/orgs","repos_url":"https://api.github.com/users/serge-sans-paille/repos","events_url":"https://api.github.com/users/serge-sans-paille/events{/privacy}","received_events_url":"https://api.github.com/users/serge-sans-paille/received_events","type":"User","site_admin":false},"html_url":"https://github.com/serge-sans-paille/pythran-stories","description":"pythran blog","fork":false,"url":"https://api.github.com/repos/serge-sans-paille/pythran-stories","forks_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/forks","keys_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/keys{/key_id}","collaborators_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/teams","hooks_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/hooks","issue_events_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/issues/events{/number}","events_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/events","assignees_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/assignees{/user}","branches_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/branches{/branch}","tags_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/tags","blobs_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/git/refs{/sha}","trees_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/git/trees{/sha}","statuses_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/statuses/{sha}","languages_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/languages","stargazers_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/stargazers","contributors_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/contributors","subscribers_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/subscribers","subscription_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/subscription","commits_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/commits{/sha}","git_commits_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/git/commits{/sha}","comments_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/comments{/number}","issue_comment_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/issues/comments{/number}","contents_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/contents/{+path}","compare_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/compare/{base}...{head}","merges_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/merges","archive_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/downloads","issues_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/issues{/number}","pulls_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/pulls{/number}","milestones_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/milestones{/number}","notifications_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/labels{/name}","releases_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/releases{/id}","deployments_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/deployments","created_at":"2016-03-08T20:14:31Z","updated_at":"2018-09-24T14:19:58Z","pushed_at":"2018-10-31T17:13:19Z","git_url":"git://github.com/serge-sans-paille/pythran-stories.git","ssh_url":"git@github.com:serge-sans-paille/pythran-stories.git","clone_url":"https://github.com/serge-sans-paille/pythran-stories.git","svn_url":"https://github.com/serge-sans-paille/pythran-stories","homepage":"http://serge-sans-paille.github.io/pythran-stories/","size":3366,"stargazers_count":1,"watchers_count":1,"language":"HTML","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":3,"mirror_url":null,"archived":false,"open_issues_count":1,"license":null,"forks":3,"open_issues":1,"watchers":1,"default_branch":"gh-pages"}},"base":{"label":"serge-sans-paille:master","ref":"master","sha":"58345cfd3d7df184dec6585d39d92e5e8bcf12aa","user":{"login":"serge-sans-paille","id":863807,"node_id":"MDQ6VXNlcjg2MzgwNw==","avatar_url":"https://avatars1.githubusercontent.com/u/863807?v=4","gravatar_id":"","url":"https://api.github.com/users/serge-sans-paille","html_url":"https://github.com/serge-sans-paille","followers_url":"https://api.github.com/users/serge-sans-paille/followers","following_url":"https://api.github.com/users/serge-sans-paille/following{/other_user}","gists_url":"https://api.github.com/users/serge-sans-paille/gists{/gist_id}","starred_url":"https://api.github.com/users/serge-sans-paille/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/serge-sans-paille/subscriptions","organizations_url":"https://api.github.com/users/serge-sans-paille/orgs","repos_url":"https://api.github.com/users/serge-sans-paille/repos","events_url":"https://api.github.com/users/serge-sans-paille/events{/privacy}","received_events_url":"https://api.github.com/users/serge-sans-paille/received_events","type":"User","site_admin":false},"repo":{"id":53442021,"node_id":"MDEwOlJlcG9zaXRvcnk1MzQ0MjAyMQ==","name":"pythran-stories","full_name":"serge-sans-paille/pythran-stories","private":false,"owner":{"login":"serge-sans-paille","id":863807,"node_id":"MDQ6VXNlcjg2MzgwNw==","avatar_url":"https://avatars1.githubusercontent.com/u/863807?v=4","gravatar_id":"","url":"https://api.github.com/users/serge-sans-paille","html_url":"https://github.com/serge-sans-paille","followers_url":"https://api.github.com/users/serge-sans-paille/followers","following_url":"https://api.github.com/users/serge-sans-paille/following{/other_user}","gists_url":"https://api.github.com/users/serge-sans-paille/gists{/gist_id}","starred_url":"https://api.github.com/users/serge-sans-paille/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/serge-sans-paille/subscriptions","organizations_url":"https://api.github.com/users/serge-sans-paille/orgs","repos_url":"https://api.github.com/users/serge-sans-paille/repos","events_url":"https://api.github.com/users/serge-sans-paille/events{/privacy}","received_events_url":"https://api.github.com/users/serge-sans-paille/received_events","type":"User","site_admin":false},"html_url":"https://github.com/serge-sans-paille/pythran-stories","description":"pythran blog","fork":false,"url":"https://api.github.com/repos/serge-sans-paille/pythran-stories","forks_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/forks","keys_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/keys{/key_id}","collaborators_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/teams","hooks_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/hooks","issue_events_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/issues/events{/number}","events_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/events","assignees_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/assignees{/user}","branches_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/branches{/branch}","tags_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/tags","blobs_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/git/refs{/sha}","trees_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/git/trees{/sha}","statuses_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/statuses/{sha}","languages_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/languages","stargazers_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/stargazers","contributors_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/contributors","subscribers_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/subscribers","subscription_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/subscription","commits_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/commits{/sha}","git_commits_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/git/commits{/sha}","comments_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/comments{/number}","issue_comment_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/issues/comments{/number}","contents_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/contents/{+path}","compare_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/compare/{base}...{head}","merges_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/merges","archive_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/downloads","issues_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/issues{/number}","pulls_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/pulls{/number}","milestones_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/milestones{/number}","notifications_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/labels{/name}","releases_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/releases{/id}","deployments_url":"https://api.github.com/repos/serge-sans-paille/pythran-stories/deployments","created_at":"2016-03-08T20:14:31Z","updated_at":"2018-09-24T14:19:58Z","pushed_at":"2018-10-31T17:13:19Z","git_url":"git://github.com/serge-sans-paille/pythran-stories.git","ssh_url":"git@github.com:serge-sans-paille/pythran-stories.git","clone_url":"https://github.com/serge-sans-paille/pythran-stories.git","svn_url":"https://github.com/serge-sans-paille/pythran-stories","homepage":"http://serge-sans-paille.github.io/pythran-stories/","size":3366,"stargazers_count":1,"watchers_count":1,"language":"HTML","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":3,"mirror_url":null,"archived":false,"open_issues_count":1,"license":null,"forks":3,"open_issues":1,"watchers":1,"default_branch":"gh-pages"}},"_links":{"self":{"href":"https://api.github.com/repos/serge-sans-paille/pythran-stories/pulls/15"},"html":{"href":"https://github.com/serge-sans-paille/pythran-stories/pull/15"},"issue":{"href":"https://api.github.com/repos/serge-sans-paille/pythran-stories/issues/15"},"comments":{"href":"https://api.github.com/repos/serge-sans-paille/pythran-stories/issues/15/comments"},"review_comments":{"href":"https://api.github.com/repos/serge-sans-paille/pythran-stories/pulls/15/comments"},"review_comment":{"href":"https://api.github.com/repos/serge-sans-paille/pythran-stories/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/serge-sans-paille/pythran-stories/pulls/15/commits"},"statuses":{"href":"https://api.github.com/repos/serge-sans-paille/pythran-stories/statuses/8c90afed5d8d12045335b1a222affa6d07c9fefd"}},"author_association":"OWNER"}}
{"actor":{"display_login":"HadrienG2"}}