Devoxx Belgium 2019 - Day 3

LINEでは年に1回の海外カンファレンス補助があるので、ベルギーのDevoxxに来てます。

DevoxxはヨーロッパのJavaコミュニティで、ロンドンやパリなど各地でカンファレンスを行なっていますが、ベルギーが最大です。
毎年、Javaのびっくり発表がDevoxx Belgiumというイベントであるというのを認識していて気になっていたのですが、今回初めて来てみました。

今日はConference Daysの初日でキーノートから始まりました。
https://devoxx.be/wednesday-schedule/

今日聞いたのはキーノートの他に次のセッションですが、Spring BootをGraalVM Native Imageで動かすセッションが一番おもしろかったです。

KeyNote

Conference Daysの初日ということで、キーノートから始まります。
キーノートは3つのセッションにわかれていました。
ところでDevoxx Belgiumは映画館で行われていて、各部屋300-500人くらい入る感じですが、キーノートで一気に数千人入るような部屋はありません。なので、一番大きい部屋でキーノートが行われて他の部屋に配信される感じになっています。
この部屋には話してる人いませんね。
f:id:nowokay:20191107104927j:plain

この部屋にいました。
f:id:nowokay:20191107105527j:plain

Welcome to Devoxx: practical info

最初のキーノートはDevoxxについての説明です。
Devoxxはヨーロッパを中心に活動するコミュニティで、年間21のイベントをやっていて、先週がウクライナで来週がモロッコらしい。
その中でも最大なのがこのベルギーで、今年は3300人の登録とのこと。去年3500人でめっちゃ混んでたから3300人で打ち止めたということらしい。
そして去年は4ヶ月でsold outだったのが、今年は10日でsold outだったとか。来年はもっと早くなる気がする。
抽選にするかどうかということを話していました。

The Hitchhiker’s Guide to Diversity (Don't panic!)

2番目のセッションはダイバーシティについて。
なのですが、途中で配信が切れてしまった・・・
f:id:nowokay:20191107102256j:plain

「ゴスリンが話してくれたんだけどつないだ瞬間切れた」とか冗談を言ってましたが、4K対応したら電源が追いつかなくて落ちたということらしい。

Qualities of a Highly Effective Architect

よいアーキテクトがどうのというセッション。
パワポアーキテクトになってはいけない、という言葉が印象的
f:id:nowokay:20191107105607j:plain

Abstractions Without Regret with GraalVM

GraalVMのセッション。
だけどやはりNative Imageが中心になりますね。

今月出る19.3でJava 11をサポートするそうな。
f:id:nowokay:20191107110253j:plain

あとのSpringのセッションのほうが知らない情報でてたな。

Developing Java applications leveraging the Quantum Internet

JavaFXがんばってるJohan Vosさんの量子通信の話。 f:id:nowokay:20191107110931j:plain

途中で覗き見とかが難しいのでセキュアだと。
SuperpositionとかEntanglementとか量子の話をしたあと、スイッチとか入れるの難しいよねという話をして、ただスイッチ作れれば通信ができていいってことを話してました。
f:id:nowokay:20191107110759j:plain

そして、Javaでつくってる量子コンピュータシミュレータの紹介。
https://github.com/gluonhq/strange

Implementing a Simple JVM in Rust

RustでJVMを実装する話
f:id:nowokay:20191107111010j:plain

GCは実装してないということなので、unit256_tさんがRustで作ったJVMのほうがGCJITもあって実装が進んでますね。

会場への問いかけで、Rust使ってる人という質問には1/4くらいが手をあげてたのだけど、Rustをプロダクトで使ってる人という質問はだれも手をあげなかった。まあJavaイベントだからね。

簡単な実装をする上でのJVMのだいたいの仕組みというのがわかりやすくてよかった。
f:id:nowokay:20191107111239j:plain

あとはRustでの実装の説明 f:id:nowokay:20191107111355j:plain

Running Spring Boot applications as GraalVM native images

SpringをGraalVM Native Imageで動かす話
f:id:nowokay:20191107111701j:plain

Java Buildpack Memory Calculatorというのを紹介していました。メモリ使用量やクラス数から最適なオプションを計算してくれるユーティリティなのかな。
https://github.com/cloudfoundry/java-buildpack-memory-calculator
f:id:nowokay:20191107112021j:plain

Parallel GCはGraalVM EEに入るとか。
f:id:nowokay:20191107112545j:plain

Native Imageに必要な設定などはSpring Graal Nativeを見ればいいぽい
https://github.com/spring-projects-experimental/spring-graal-native

Spring Boot 2.2ではCGLIBやProxyを使わないようにできるので、native imageに優しくなっているらしい。すごい。
f:id:nowokay:20191107112748j:plain

あと、AOT用の工夫はJITでも有効だと言ってました。
相当がんばっとるな。
GraalVMチームと協力して開発をすすめているらしい。

Understanding Low Latency JVM GCs

G1GC、Shenandoah、ZGC、C4の説明のセッション。
f:id:nowokay:20191107113132j:plain

GCの使い分けのまとめ。しかし、ZGCはWindows対応するっぽいので、Windowsならってとこは変わりそう。
f:id:nowokay:20191107113455j:plain

しかし、話とともにちょっとずつ資料を表示するスタイルで疲れた・・・
GC使い分けとか、ちょっとずつ出されても・・・みたいな。

Evolving Java for the Serverless Era with Micronaut

Micronautのセッションなんだけど、初日に聞いたセッションの一部ぽいので途中退出。
f:id:nowokay:20191107113742j:plain

What's coming in Scala 3

ということでScala 3のセッションに。
f:id:nowokay:20191107113845j:plain

Scalaようわからんけど、楽しそうでした。

Meet & Greet in exhibition floor until 20h30

今日は会場でビールがでました。
ブロンド系なんだけど、銘柄まではわからず。ベルギービールを当てるのは種類が多すぎるし日本で飲みにくいものも多いので相当難しい・・・
f:id:nowokay:20191107113946j:plain

今日のビール

で、ホテルに戻って、気になっていたDuvelの看板がでている店に。
f:id:nowokay:20191107114330j:plain

ボトルかよ、という気持ちw
f:id:nowokay:20191107114242j:plain

そして、料理もない店でした。。。まあ4Eurでお釣りが来るくらい安くていいのだけど。ビールだけ出て料理は出ない店が結構多いふいんき

いつもどおりノンアルヒューガルデンを買って・・・と思ったら、ふつうのヒューガルデンだった。
f:id:nowokay:20191107114947j:plain

夜のアントワープ駅もきれい。
f:id:nowokay:20191107114621j:plain

聞かなかったセッション

ついでに、聞きたいけど裏番組だったりで聞かなかったのをまとめておきます。
Project Loom: Helping Write Concurrent Applications on the Java Platform

Quarkus why, how and what by Emmanuel Bernard

Java on ARM Theory, Applications and Workloads

Your Program as a Transpiler: Applying Compiler Design to Everyday Programming

Devoxx Belgium 2019 - Day 2

LINEでは年に1回の海外カンファレンス参加補助があるので、ベルギーのDevoxxに来ています。
(夏のJVMLSは自費です)

Devoxxは月・火のDeep Dive Daysとと水・木・金のConference Daysにわかれていて、今日はDeep Dive Daysの2日目です。
https://devoxx.be/tuesday-schedule/

会場はKinepolisという映画館
f:id:nowokay:20191106093910j:plain

映画館だけあって、スクリーンはでかいし席はすわりごこちいいし後ろの席からも見やすいです。

Solving Memory Leaks in the JVM

Kirkさんのセッションです。Deep Diveということで、3時間のコマです。
https://devoxx.be/talk/?id=109305 f:id:nowokay:20191106101215j:plain

セッションとしては、VIsualVMやjClarity、jcmd、jmapを使ってメモリリークを探す説明でした。
f:id:nowokay:20191106101416j:plain

しかしながら、英語がよく聞き取れなかったり説明をききのがしてたりで、なんのためにそのコマンドでオブジェクトがたくさん使われてるか発見するのかというのがよくわからなかった・・・
YouTubeでは字幕もつくので、見直すといいんではなかろうか・・・

Migrating AWS Lambda's frontend from Java 8 to 11

もとのタイトルは「Learnings from migrating a production service from JDK8 to JDK 11」でしたが、プレゼンタイトルではLambda FrontendのMigrationということになっていました。
https://devoxx.be/talk/?id=106451
f:id:nowokay:20191106102039j:plain

それでLambdaの説明が始まると出ていく人が結構いましたが、Lambda上で動かすコードをMigrateするのではなくて、Lambda自体の認証などを行うフロントエンド部分をMigrateしたという話で、おもしろかったです。

Java 8からJava 11でパフォーマンスにインパクトがあったのはG1GCがデフォルトになったこととCompact Stringだとのこと。
f:id:nowokay:20191106095653j:plain
あと、-XX:+UseStringDeduplicationで文字列の重複をなくすとメモリ利用が80%へったけどGC停止時間は増えたと。結局これどうしたんだろう?ライブラリ中の文字列重複を省いていったのかな。

デプロイは小さなリージョンから大きなリージョンへ。
f:id:nowokay:20191106095008j:plain

結果としてGC停止時間はかなり減っています。
f:id:nowokay:20191106095937j:plain

あと、レイテンシーが99パーセンタイルだと20%減って、99.99パーセンタイルだと33%減った、と。
f:id:nowokay:20191106095847j:plain

総じて、バグはなくパフォーマンスもよくなってよかった、という話でした。

GraalVM native images explained

Olegさんの、GraalVM native imageのセッション。身振り大きく説明していて、楽しかった。
https://devoxx.be/talk/?id=104405
f:id:nowokay:20191106102128j:plain

とりあえず前提として、native imageによるAOTと通常のJVMでのJITでこういう違いがあるよ、という話。
f:id:nowokay:20191106103433j:plain

クラスひとつでどれだけコンパイル時間がかかるんだ、ってことに関しては、システムクラスがたくさん使われているという話なのだけど、それを説明するために利用しているクラスを全部可視化するというのをやっていて、これすごく興味ある。
f:id:nowokay:20191106102250j:plain

あと、リフレクション使ってるコードに対してnative-image-agentを使って自動的に利用クラスの設定ファイルを出力するというデモをやっていました。
こんな感じで入力されたメソッドを呼び出すデモ。
f:id:nowokay:20191106103400j:plain

普通にnative imageを作るとうまく実行されないので、設定ファイルが必要なのでJava Agentを使うと。
f:id:nowokay:20191106102643j:plain

こんなJSONができています。

[
{
  "name":"HelloReflection",
  "methods":[{"name":"foo","parameterTypes":[] }]
}
]

あと、プログラムから読み込むリソースファイルなどは設定を書いておく必要があるけどMicronautとかは あらかじめ書いていてくれるよ、という話。
f:id:nowokay:20191106102920j:plain

最終的にはJITのいいところも取り込まれればいいよね、ってことでした。
f:id:nowokay:20191106103613j:plain

Choosing a JDK: Ask the Distributors

JDKバイナリ配布する人にいろいろ聞いてみよう、というBOFです。 https://devoxx.be/talk/?id=21103
f:id:nowokay:20191106103824j:plain

まんなかにいるAzulのSimon Ritterさんによる進行で、右はBellSoftのLibericaの人。左のひとはだれだったかよくわからない・・・
あと、プロジェクタの左側にSAP Machineの人が座っていました。
そんな感じで、JDKのバイナリ配布をしてる人たちがいろいろ話すBOFでした。

JavaLinuxみたいにいろいろなディストリビューションがあるんだという話。

Javaが動くVMの一覧。
f:id:nowokay:20191106103817j:plain

BOFにしては人が多くて50人くらい入っていました。 いろいろ挙手があったのだけど、Oracle JDKを使ってる人という質問には半分以上が手をあげていた。
Java 8を使ってる人がほとんどで、Java 11が1/4、13を使ってる人も少し、という感じ。
Intel CPUがほとんどで、ARM使ってる人が2人かな。
あと、Dockerで動かしてる人が1/3くらいいて、その半分はKubernetes

OpenJDKのDocker Imageを使ってる人という質問に手をあげる人はだれもいなくて、ダウンロードはたくさんあるので木になるとSimonさんは言ってた。

Dockerの話になったのは、Docker Imageを提供しないのかという質問をした人がいたからで、その人は最小のイメージが欲しいといっていたので、Libericaの人がAlpineを使えと切ってすてていた。そういえばLibericaの人は(Project Portola)https://openjdk.java.net/projects/portola/やってる人だったな。

サポートはどういう風にやっているかという質問があって、パッチについて - A: OpenJDKに還元する。変更は他のディストリビューションにも広まる - B: OpenJDKに提供しない

という選択肢があるし、お金払ってサポートするのだからBのほうがいいかもしれないけど、コミュニティに情報を共有するほうがいい、って言ってた気がする。

Oracle JDKとOpenJDKの違いについて、会場の人がJavaFXは入ってないしJava SEでもない、どこもJavaFXを入れていないということを言う人がいたんだけど、前にいるSimonさんとLibericaの人が「We do!!!」って手をあげたのがおもしろかった。

終了

電車で帰ります。
f:id:nowokay:20191106110914j:plain

今日のベルギービールはPrimus。
f:id:nowokay:20191106110901j:plain

まあ、普通のピルスナーなんで、ベルギーまで来て飲むほどのものではないけど、他の店が閉まっていたので・・・
BOFまで聞いて帰ると21時とかで店がしまっていて選択肢がなくなるのがつらい。
でもBier Centralでハンバーガーのほうがよかったかな。

今日もノンアルのヒューガルデンを買って帰ったのだけど、お店のおにいさんに「お前は酒飲みに見えるのになんでノンアルを買うんだ!」と聞かれました。
日本から来て、これは日本で売ってないというと、日本の酒はニッカとかヤマサキとかウイスキーが好きだと言っていました。
f:id:nowokay:20191106110838j:plain

ということで、明日からはConference Daysです。おやすみなさい。

エンジニアHubのインタビュー記事がでました

エンジニアHubのインタビュー記事が出ました。
employment.en-japan.com

インタビューの前に質問集をもらったんですけど、この質問がよくできていて、そのまま記事にしてもいいのではーと思うくらいの内容でした。

記事中で触れてる無設定Strutsは このあたりですね。もうソースとかはリンク切れだけど。
無設定Strutsできました - きしだのHatena

よく見ると、S2Strutsにそのまま無設定Strutsという機能名で入っていた。
http://s2struts.seasar.org/ja/1.3/zeroconfig.html

Dynamic CDSよりJava10からある自力ダンプの方が起動が速い

昨日のエントリでDynamic CDSを使いましたが、自分でダンプしたクラスデータを使うほうが速くなりました。
Java 13のDynamic CDSで想像以上に起動速度が速くなった - きしだのHatena

Java 10からOpenJDKでもApp CDSが使えるようになりました。Oracle JDKでは8u40からあるっぽい。
JEP 310: Application Class-Data Sharing

Dynamic CDSと違うのは、クラス一覧を指定しないといけないところ。

クラス一覧は、こんな感じで-XX:DumpLoadedClassListでファイル名を指定すると生成されます。

$ java -Xshare:off -XX:DumpLoadedClassList=mn.lst -jar build/libs/myapp-0.1.jar 

そうするとこんな感じでロードされたクラス一覧が記録されます。

java/lang/Object
java/lang/String
java/io/Serializable
java/lang/Comparable
java/lang/CharSequence
java/lang/Class
...

このクラス一覧を使ってクラスデータをダンプします。このとき、アプリケーションは実行されません。ダンプだけ行われます。

$ java -Xshare:dump -XX:SharedClassListFile=mn.lst -XX:SharedArchiveFile=mn13.jsa -jar build/libs/myapp-0.1.jar
Allocated shared space: 3221225472 bytes at 0x0000000800000000
Loading classes to share ...
Preload Warning: Cannot find jdk/internal/misc/JavaLangRefAccess
Preload Warning: Cannot find jdk/internal/misc/SharedSecrets
Preload Warning: Cannot find jdk/internal/misc/JavaIOFileDescriptorAccess
Preload Warning: Cannot find jdk/internal/misc/JavaNioAccess
...

実行はDynamic CDSを使う場合と同じです。

$ java -XX:SharedArchiveFile=mn13.jsa -jar build/libs/myapp-0.1.jar 

Java 11ではそれぞれに-XX:+UseAppCDSをつけておく必要があります。
計測したら、だいぶ速くなっていました。6回実行して2回目以降5回分の平均をとっています。

JVM起動 アプリケーション起動
No CDS 149.6 1028.6
Default CDS 98.6 1009.2
Dynamic CDS 89.2 688.8
AOT+DynCDS 144 625.6
App CDS 93 451.4

なにも指定していない場合の倍の速さで起動していますね。

f:id:nowokay:20191019001323p:plain

Java 13のDynamic CDSで想像以上に起動速度が速くなった

Java 13で、読み込み済みのクラスデータを終了時に保存するDynamic CDSが導入されました。
https://openjdk.java.net/jeps/350

で、試してみたら結構起動速度が変わっていました。

Micronautで試してみます。

追記: Java 10でApplication Class-Data Sharingが入っているので、自分でクラスリストを作ってダンプすれば同等のことができていたのだけど、面倒さが低減された感じです。LTSであるJava 11ではAppCDSを使うといいと思います。

追記2: 自分でダンプしたほうがかなり速かった
Dynamic CDSよりJava10からある自力ダンプの方が起動が速い - きしだのHatena

準備

インストールは全部SDKMAN!で行います。(Windowsの場合はCygwinかWSLを使います)

$ curl -s "https://get.sdkman.io" | bash

ターミナルを開き直すとSDKMAN!が使えるようになります。
まずはJDKを。Micronautは現時点ではJDK13でビルドできないので、JDK12を使います。

$ sdk use java 12.0.2-open

次にMicronautをインストールします。

$ sdk use micronaut 1.2.4

Micronautのアプリケーションを作成します。

$ mn create-app myapp

できたフォルダに移動。

$ cd myapp

ビルドします。テストでこけることがあるので、テストをスキップ。

$ ./gradlew -x test build

実行してみます。

$ java -jar build/libs/myapp-0.1.jar 
21:02:22.782 [main] INFO  io.micronaut.runtime.Micronaut - Startup completed in 1103ms. Server Running: http://localhost:8080

終了はctrl+cで。

Dynamic CDSを試してみる

Dynamic CDSでクラスデータを保存するときは-XX:ArchiveClassesAtExitをつけてアーカイブファイル名を指定します。

$ java -XX:ArchiveClassesAtExit=mn.jsa -jar build/libs/myapp-0.1.jar 
myapp $ java -XX:ArchiveClassesAtExit=mn.jsa -jar build/libs/myapp-0.1.jar 
22:09:12.011 [main] INFO  io.micronaut.runtime.Micronaut - Startup completed in 1681ms. Server Running: http://localhost:8080
^C22:09:14.530 [Thread-2] INFO  io.micronaut.runtime.Micronaut - Embedded Application shutting down
[4.593s][warning][cds] Skipping io/micronaut/http/client/$DefaultHttpClientConfiguration$DefaultConnectionPoolConfigurationDefinition: Not linked
[4.593s][warning][cds] Skipping io/reactivex/internal/operators/mixed/ObservableSwitchMapCompletable: Not linked
[4.593s][warning][cds] Skipping io/reactivex/internal/operators/completable/CompletableTimeout: Not linked
...

18MBのファイルができています。

$ ls -l -h mn.jsa
-r--r--r--  1 kishida  staff    18M 10 17 22:09 mn.jsa

このシェア用アーカイブファイルを利用するときは-XX:SharedArchiveFileをつけてアーカイブファイルを指定します。

$ java -XX:SharedArchiveFile=mn.jsa -jar build/libs/myapp-0.1.jar 

結果はあとでまとめますが、結構起動が速くなりました。

結果

ということで結果です。
Javaの標準クラスに関してはDefault CDSとしてJDK12から用意されるようになっていますが、これを使わないものも試してみました。
-Xshare:offをつけるとDefault CDSファイルが使われなくなります。

$ java -Xshare:off -jar build/libs/myapp-0.1.jar

もうひとつ、Java 9から導入されているAOTも試してみます。今回はjava.baseモジュールだけAOTをかけてみます。

$ jaotc --output=libjava.base.so --module java.base

これを使うときは-XX:AOTLibraryをつけてライブラリファイルを指定します。

$ java -XX:AOTLibrary=./libjava.base.so -XX:SharedArchiveFile=mn.jsa -jar build/libs/myapp-0.1.jar

6回連続で起動して2番目以降の平均を計測値にします。
また、Micronautの起動時間はmainメソッド以降の実行時間なので、mainメソッドの最初に

System.out.println(ManagementFactory.getRuntimeMXBean().getUptime());

をつけてJVM自体の起動時間も計測しています。

package myapp;

import io.micronaut.runtime.Micronaut;
import java.lang.management.ManagementFactory;

public class Application {

    public static void main(String[] args) {
System.out.println(ManagementFactory.getRuntimeMXBean().getUptime());
        Micronaut.run(Application.class);
    }
}
JVM起動 アプリケーション起動
No CDS 149.6 1028.6
Default CDS 98.6 1009.2
Dynamic CDS 89.2 688.8
AOT+DynCDS 144 625.6

ということでこんな結果に。
Default CDSではアプリケーション起動時間はあまり変わりませんがJVMの起動時間が短くなっています。そしてDynamic CDSでアプリケーションのクラスデータも再利用すると、アプリケーション起動時間がかなり縮まっていますね。
残念なのはAOTで、アプリケーション起動時間が縮まっているけどJVM起動時間がすこしのびて、トータルでは結局同じくらいの起動時間になっています。
f:id:nowokay:20191017224337p:plain

Vector APIを試す

Vector APISIMD命令をJavaから利用するためのAPIです。
Project Panamaの一部ということになっていますが、最近はなんかPanamaとは別扱いになってる気がします。

Vector APIはJEPがすでに作成されていて、感触としてはJDK 14に入りそうな勢い。
JEP 338: Vector API (Incubator)
※追記(2020/10/24) JDK16に入ることになりました。

ビルド

いまのところ簡単に試せるバイナリは提供されていないので、自分でビルドする必要があります。
※追記(2020/10/24) JDK16 ea21から取り込まれているのでビルド不要で試せます。

いままでJDKのビルドをするときにはソースをMercurialでとってきていましたが、OpenJDKのソースはGitHubにミラーされるようになったので、Gitを使うほうが断然速いです。

$ git clone https://github.com/openjdk/panama/

Vector APIはvectorIntrinsicsブランチで開発されていてmasterには取り込まれていないので、ブランチを切り替える必要があります。

$ cd panama
$ git checkout vectorIntrinsics

あとは通常どおりビルドします。

$ bash configure
$ make images

足りないライブラリがあればconfigure時に示してくれるはずなので、インストールして再び試すといいです。

JShellで試す

それでは、JShellで試してみましょう。Vector APIモジュールはデフォルトでは有効になっていないので、java / javac / jshell各コマンドに--add-modules jdk.incubator.vectorをつけてモジュールを読み込む必要があります。

$ build/linux-x86_64-server-release/images/jdk/bin/jshell --add-modules jdk.incubator.vector
|  Welcome to JShell -- Version 14-internal
|  For an introduction type: /help intro

jehsll> import jdk.incubator.vector.*

jshell> var SP = DoubleVector.SPECIES_256
SP ==> Species[double, 4, S_256_BIT]

jshell> var v1 = DoubleVector.fromValues(SP, 1, 2, 3, 4)
v1 ==> [1.0, 2.0, 3.0, 4.0]

jshell> v1.add(2)
$4 ==> [3.0, 4.0, 5.0, 6.0]

jshell> var v2 = DoubleVector.fromValues(SP, 2, 3, 4, 5)
v2 ==> [2.0, 3.0, 4.0, 5.0]

jshell> v1.add(v2)
$6 ==> [3.0, 5.0, 7.0, 9.0]

このように複数の値に対してひとつの命令で演算が行えることがわかります。
コードを書く際に最初に注意する点としては、パッケージはjdk.incubator.vectorに入っているということと、どの型のどのサイズのVectorを使うか示すためにSPECIESが必要、というところですね。
あとの演算は、JavaDocを見れば比較的わかりやすいんではないかと思います。
jdk.incubator.vector (Java SE 13 & JDK 13 [ad-hoc build])

気がむいたらAPIについてもまとめます。
※追記(2020/10/24) fromValuesは正式版からは外れてるようなので代わりにfromArray(SP, new double[]{1, 2, 3, 4}, 0)などとする必要があります。

Vector APIを理解するためにSIMD命令をCで試す

JavaVector APISIMD命令を呼び出すためのAPIです。
ということで、実際にSIMD命令を知っておいたほうが理解が深まる気がします。
ただ、直接SIMD命令を試すのはめんどいので、C++から呼びだしてみます。

Cの文法とかだいぶ忘れてるというか知らないものが多いので、適当にぐぐりながら書いてみました。

#include<cstdio>
#include<x86intrin.h>

typedef __attribute__((aligned(32))) struct {
    double x;
    double y;
    double z;
    double w;
} Vec;

int main(void) {
  Vec v1 = {2, 3,4, 0};
  Vec v2 = {3, 4, 5,0};
  const __m256d d1 = _mm256_load_pd((double*)&v1);
  const __m256d d2 = _mm256_load_pd((double*)&v2);
  const __m256d r = _mm256_add_pd(d1, d2);
  Vec *v3 = (Vec*)&r;
  printf("%f, %f, %f\n", v3->x, v3->y, v3->z);
}

最初まったくコンパイルが通らなくてあきらめたんだけど、 Twitterで-mavx2とかつければいいと教えてもらいました。
https://twitter.com/objectxplosive/status/1165307957417930752

$ gcc -mavx2 hello.cpp -o hello
$ ./hello
5.000000, 7.000000, 9.000000

無事うごいた。