2021年1月1日金曜日

やはりC++はCよりも遅い?

とりあえず、残りは細かいことが多いので後で書かないと思うので一般的なことだけ少し書き残しておきます。

大人の事情もあるので具体的なことは勘ぐらずに一般論の個人的な考えとしてお願いします。まぁ、今回の内容には直接の知財問題は無いとは思いますが。

例えば、ある程度大きなプログラムで、昔はCで書かれていて、バージョンが上がる度にプログラムは大きくなり、大きいプログラムのメンテナンスや開発効率のために、また更に新しい規格のC++の記法を用いたりしてバージョンアップをしていくことは往々としてよくある話かと思います。

記法が高度で複雑になるほど、最適化も難しくなるはずです。

C言語程度の単純な記法に対しては、「__builtin_expect()」 とか 「__attribute__()」 とか 「#pragma」 のいろいろな最適化指定も効きましたが、高度な記述の最適化に必要な高度なコンテキストをコメント等の記述でコンパイラに伝えることは難しいのか、挙げた以上のものはコンパイラのマニュアルにはありません。

代わりにあるのが、PGO (Profile-Guided Optimization) ビルドです。速くあってほしい最適化したい処理を実際に実行し、その結果を基に最適なコンパイルをするわけです。論理構造が同じであれば、
「PGOを使って初めて、100%の確率でC相当の記述の時代と同等の性能」
となるわけです。
そうでなければ、コンパイラの解釈により確率的に最適ではないコードが生成される可能性があり、多少遅くなります。そしてその性能劣化はプログラムが大きくなるほど、実行する処理の関係範囲が大きいほど紛れ込む可能性が増えます。

PGOビルドを使わなければ、見かけ上は全然関係ない変更なのに、日々変更を積み重ねる度に徐々に遅くなっていくように見えます。これが(大きな)C++のプログラムが処理によってはCレベルの時代よりも遅くなる大きな理由でしょう。

PGOビルドをベースにすると高度なC++記述の大きなプログラムの真の性能問題が見えるようになります。
※性能劣化したリビジョンを探す過去への真の旅が始まります。7、8年くらいは歴史を見ますか…(遠い目)。
※この、PGOしないことによる性能劣化ノイズは結構大きく、場合によっては劣化の半分はPGOで解決するようです。
 (まぁ、それより大きいものは非PGOビルドでも見えやすかったからでしょうが。)

一つだけアドバイスをするなら、PGOベースでそのような過去の旅をする場合、プログラムがスレッドをdetach(joinしないで管理投げっ放し)する場合にはGCCは上手くプロファイリングできないようなので、clangを使ったほうがいいでしょう。
※MySQLはdetachするスレッドがいくつかあります。

というわけで、具体的な旅の話は旅が終わって結果が世に出てからですね。例によって。いつの日か。

それでは、性能を追求する仲間たち(誰も居ないかな?)の良い旅を願います。

2020年12月31日木曜日

MySQL 8.0 の InnoDB の log_sys周り の話

思い出せるうちに思い出せる範囲で…

例によって世に出る頃には全く違うことに取り組んでいるので、忙しくしてると何も書かずに終わってしまうのですが、こんなご時世、年末年始休暇があっても何も用事がなく折角なのですこし書き残します。本来は本家開発者のブログで英語で書くべきなんですが、込み入った話を英語で書く労力をかけるくらいなら次の問題解決にかけたほうがいいので、とりあえず日本語で書き残します…

私がMySQL界を離れている間にリリースされた8.0になってlog_sysのデザインが新しくなり、スケールが良くなったのですが、既存のハードを利用する大半のユーザーには、未だ荒かった実装のせいでデメリットの方が大きかったと思います。2019末くらいには悪い挙動と原因はある程度分かっていましたが、修正リリースは2020後半になってしまいました。

既存のスペックのハードウェアと、CPUコア多数搭載の最新ハードとでは、ベストの性能を出すために共通している部分も多いのですが、違う部分もどうしてもあります。8.0.22での log_sys の大半の修正は共通にできたのですが、writer_thread と flusher_thread の利用に関してだけは、どうしても利害が相反してしまったので仕方なくinnodb_log_writer_threads というオプションを導入せざるを得ませんでした。

CPUコア数が(死ぬほど)多いとCPUコアが余ったり各コアのCPU使用率に余裕があったりするわけで、
CPUコアや使用率を無駄にしてでも余ったCPUコアに仕事を振ってスケールを上げる
というのが目先のベストの戦略かと思います。しかし、CPUコア数の余剰分が無い(まぁ、普通予算が余らなければオーバースペックなCPUにはしないので普通無い)場合はCPUは十分使い切れるので、その戦略で設計されたソフトウェアは「只遅いだけ」のものとなります。

というわけで、共通部分のCPU無駄食いは直したのですが、writer_thread と flusher_thread については「高スペックで必要」、「低スペックでは邪魔」なので、innodb_log_writer_threads オプションがあります。

問題はCPUリソースなので、IOがボトルネックの場合にはON/OFFで差は出ないと思いますが、
全体でのCPU使用率が高い(つまり、全CPUが元々ちゃんと働いている。又は他のコンポーネントと相乗り)場合に、
innodb_log_writer_threads はOFFにしたほうが良いでしょう。

実は、innodb_log_writer_threads 以外で修正した部分の方が影響は大きいので、基本8.0.22にしさえすれば更新系の性能問題は減ると思います。

細かい話では、
logのflushとcheckpointの頻度が環境のスペックが高いほど激増してたのですが、(writeも増えるが、InnoDBでlogのwriteは必ずOSのIOレイヤーでバッファリングされるので問題はない。 というか細かく書き出したほうが下位レイヤーでの最適化が働く余地があるのでいいこともあるらしい。)flushとchoekpointを5.7相当のストラテジーに戻した。
ということや、あとは、
8.0では5.7とは違ってlog_bufferへの書き込みは常に並列化されているので(innodb_log_writer_threads=OFFでも常に)、その書き込みがどこまで連続で終了しているか(最初の未書き込み手前までしかwriteできない)確認していく別スレッド(closer_thread)も存在したのですが、高スペックハードでもCPU無駄食いが酷かったので工夫して廃止しています。

まぁ、性能ギリギリで利用している人は居ないのでだれも気づかないのでしょうかね。
とにかくこれで、log_sys は当面直す箇所は無いと思います。

以前も log_sys の書き込み量が8.0で増えていたのを調査して直したこともありますが(8.0.20)、そもそもユーザーは誰も気づいていなかったようで直しても性能に関する反響は聞きません。
(InnoDBのログの32ビット整数表現は、上位ビットが0で埋まっているほど少ないバイト数で収まります。UNDO spaceのIDは5.7では1バイト表現できたのが、8.0になってマイナス表現側のIDを使うようになったので、UNDO space IDが4バイトになってしまってログの量が結構増えてたので、フォーマットを拡張して、マイナス表現側も2バイト程度には収まるように拡張しました。UNDO space ID自体は同じ長さまで戻ったわけではないですが、全体としてログのバイト数は5.7程度に戻ったと思います。)

自分で探して自分で直すのみですね。

なにはともあれ、念願のlog_sys修正が一段落したので次にすすめるわけです。(まだ、8.0新機能やInnoDB以外の8.0更新部分との相性が悪い部分はあるかも知れないですが)

何故「念願」だったかというと。。。。
前述の「CPU無駄食いスケール優先」は単純な性能の問題だけではなく、「他の性能劣化を隠してしまう」特性もあるからです。リソース消費と性能がちゃんと比例していないモッサリとした特性だと、裏でシングルスレッド性能劣化し放題だからです。

というわけで次の話題もあるのですが、ここまで。

次の話題は、リリースまでソースコード修正の話は書けないのですが、一般技術論は書いてもいいような気もするのだけれども、それが核心だから…さてどうしましょうかね。

2020年9月25日金曜日

index->lock の競合について 〜ベンチマークはちゃんとチューニングして〜

他に忘れないうちに書きたいこともあったのですが、世に出るまで書けないので、ソースと関係ない一般的なこと(バージョン5.7以降)を書きます。(書かない方のことは書けるようになる頃には忘れてしまうかも…)

index->lockの競合を直して欲しい。という人がいまだに居たりするのです。色々試しましたが、多分殆どの場合は理解不足・チューニング不足です。私自身はindex->lockの競合が不可避なベンチマークに結局会っていません。

特にMySQLとその他のRDBMSを比べる場合にはちゃんと最適化した負荷をかけないとMySQLが悪く見えるのでベンチマークをする際には気をつけて欲しいものです。

5.7で更新・参照並列性を高めるために導入された、index->lockのSXロック(Sロックは可能・SX/Xロックは不可)は、基本的にそのindexにpageを追加・削除するような処理をする際に保持されます。何かする度にpageの追加・削除をするような処理がindex->lockの競合を引き起こします。なので、index->lockの並列性を少し解決したところで、どうせ次のspace->latchとかの競合(index->lockより大きい範囲かも)になるので、この場合意味がありません。

「indexにpageを追加・削除するような処理を極力減らすことが唯一の解決策です。」


index->lockに関わる代表的な(性能が)悪い例が sysbench-tpcc です。sysbench向けのスクリプトですが、十分に処理を吟味すること無く、--tables なんてオプションを付けて誤魔化しているようです。
見ていきましょう。。。

ポイントは2つあります。

1.UPDATEが激しい場合は極力inplaceになるようにする。つまり、定義上固定長レコードにする。


レコードのサイズが変わる場合はサイズチェックが行われ、pageの追加・削除の可能性が出ますが、 固定長の更新の場合は、「その可能性はゼロ」です。最も性能上好ましいUPDATEです。 ここまではなんとなく知っている人も多いと思いますが、間違いやすいことがあります。

「真の固定長はNOT NULL」


nullableなカラムがあるとレコードにNULLを表現するための1ビットの領域が確保され、 NULLの場合には該当カラムの中身は0バイトになります。 つまり「NULL<->NULL以外の場合」のUPDATEでレコード長が変わりinplaceではなくなります。

sysbench-tpccでNULLからのUPDATEが起こらないように変更しましょう。 特異値を決めてNULLの代わりに使うようにします。 この場合は主に orders表 と order_line表 の初期レコードの問題みたいです。

--- tpcc_common.lua
+++ tpcc_common.lua
@@ -236,7 +236,7 @@
        o_w_id smallint not null,
        o_c_id int,
        o_entry_d ]] .. datetime_type .. [[,
-       o_carrier_id ]] .. tinyint_type .. [[,
+       o_carrier_id ]] .. tinyint_type .. [[ not null default 0,
        o_ol_cnt ]] .. tinyint_type .. [[,
        o_all_local ]] .. tinyint_type .. [[,
        PRIMARY KEY(o_w_id, o_d_id, o_id)
@@ -266,7 +266,7 @@
        ol_number ]] .. tinyint_type .. [[ not null,
        ol_i_id int,
        ol_supply_w_id smallint,
-       ol_delivery_d ]] .. datetime_type .. [[,
+       ol_delivery_d ]] .. datetime_type .. [[ not null default '1900-01-01',
        ol_quantity ]] .. tinyint_type .. [[,
        ol_amount decimal(6,2),
        ol_dist_info char(24),
@@ -510,7 +510,7 @@

       query = string.format([[(%d, %d, %d, %d, NOW(), %s, %d, 1 )]],
        o_id, d_id, warehouse_num, tab[o_id],
-        o_id < 2101 and sysbench.rand.uniform(1,10) or "NULL",
+        o_id < 2101 and sysbench.rand.uniform(1,10) or "DEFAULT",
         a_counts[warehouse_num][d_id][o_id]
         )
       con:bulk_insert_next(query)
@@ -558,7 +558,7 @@

       query = string.format([[(%d, %d, %d, %d, %d, %d, %s, 5, %f, '%s' )]],
            o_id, d_id, warehouse_num, ol_id, sysbench.rand.uniform(1, MAXITEMS), warehouse_num,
-        o_id < 2101 and "NOW()" or "NULL",
+        o_id < 2101 and "NOW()" or "DEFAULT",
         o_id < 2101 and 0 or sysbench.rand.uniform_double()*9999.99,
        string.rep(sysbench.rand.string("@"),24)
         )
TPC-Cの仕様上、これらの値は確かNULLである必要は無かったと思います。 他のベンチマークプログラムではNOT NULLになってたかも知れません。

2.同じ領域内で激しいINSERT/DELETE混合処理がある場合にはpage結合処理の閾値を下げる。


キーの順番で大きいものをINSERTし、小さいものをDELETEしていく場合には問題は起こらないと思います。

近いキー値のINSERT/DELETEの度にpageの追加・削除でバタバタしないように、 削除側の条件を下げて余裕をもたせます。 下げた分の割合でデータファイルは大き目になりますが、 性能には影響しないでしょう。 MERGE_THRESHOLD はこのために5.7から導入した方法です。(これも5.7から)

また、念の為明記しておきますが、

「二次索引のキー値の UPDATE は DELETE-INSERT」


ですので、激しく行う場合はチューニングしたほうが良いでしょう。

sysbench-tpccでは、new_orders表が主キー順ではないINSERT/DELETEが多いので 一応調整したほうがいいでしょう。(処理は多いが小さめに保たれる表なのでデメリットは少ない) とりあえず MERGE_THRESHOLD=30 くらいで。

--- tpcc_common.lua
+++ tpcc_common.lua
@@ -252,7 +252,7 @@
        no_o_id int not null,
        no_d_id ]] .. tinyint_type .. [[ not null,
        no_w_id smallint not null,
-       PRIMARY KEY(no_w_id, no_d_id, no_o_id)
+       PRIMARY KEY(no_w_id, no_d_id, no_o_id) COMMENT 'MERGE_THRESHOLD=30'
        ) %s %s]],
       table_num, engine_def, extra_table_options)
 
という感じで、他者と比較するベンチの場合にはちゃんとチューニングしてください。処理を。

※余談


ちなみにsysbenchに付属のoltp_common.luaも後者の問題があります。 二次索引のキーの変更を行う場合には、 その索引に MERGE_THRESHOLD=30 を付ければindex->lockの競合はなくなります。

--- oltp_common.lua
+++ oltp_common.lua
@@ -235,7 +235,7 @@
    if sysbench.opt.create_secondary then
       print(string.format("Creating a secondary index on 'sbtest%d'...",
                           table_num))
-      con:query(string.format("CREATE INDEX k_%d ON sbtest%d(k)",
+      con:query(string.format("CREATE INDEX k_%d ON sbtest%d(k) COMMENT 'MERGE_THRESHOLD=30'",
                               table_num, table_num))
    end
 end
というわけで、私はindex->lock競合は5.7でほぼ解決てる(というか別の競合に先にぶつかる)筈と思っているのですが…どうでしょうか?

2020年7月10日金曜日

次の次のリリースこそは…

性能フリーク(更新系)の皆様には8.0.22では違いに気づいてもらえる筈です。まだ何も言えませんが。誰も気づかないでしょうかね…。

2019年2月7日木曜日

復帰しました。

今月から中の人に復帰しました。よろしくお願いします。

弊害として、このブログの更新が減ると思われます。こちらもよろしくお願いします。

前職は丸4年在籍しましたが、技術的にも社会的にもビジネス的にもその会社でなければできないことはもう無くなったと感じて次の道を考え始めていたところ、復帰のお誘いがありましたので受けました。

ここ数年、データベース以外の分野でのトライアルで培った技術は何らかの形でMySQL/InnoDBの将来のために役立っていくと思います。が、ずっと未来の話で皆さん忘れた頃かもしれないです…

2018年11月4日日曜日

Pythonを突き詰めたらPerlを使ってた話

あ…ありのまま 今 起こった事を話すぜ!

「自作Pythonモジュールを使うスクリプトの性能を突き詰めていたと
思ったら いつのまにかPerlを使っていた」

な… 何を言っているのか わからねーと思うが
恐ろしいものの片鱗を 味わったぜ…

#!/usr/bin/perl -e$_=$ARGV[0];$ENV{'LD_PRELOAD'}=s|[^/]+$|hogehoge.so|r;exec('python',@ARGV)
import sys
import os
print sys.argv
print os.environ['LD_PRELOAD']

LD_PRELOADで、同じ場所にあるhogehoge.soをpython起動時に直接ぽく読み込みたかった(Cythonからpxdの設定だけで直で呼びたい関数があった)わけです。

shebangは、引数1個までで128バイト以下じゃないといけないのか。初めて知りました^^;。(Linuxだけか?) awkだと引数を再連結して全部拾い直すと128バイトに収まらない…無念。(引数なしなら可能)

#!/usr/bin/awk BEGIN{a=ARGV[1];sub(/[^/]+$/,"hogehoge.so",a);system("LD_PRELOAD="a"\tpython\t"ARGV[1])}

ワンライナー系の課題はPerlが強くてコンパクトなのですね…
私の技量の問題なのかな…

2018年9月26日水曜日

Webサイトの導線について 〜大量のコンテンツを興味ある人に効率よく届けるために〜

今回のエントリは、今までと同じことを別の視点から書くことになってるだけかもしれないけど、今まで良く理解できなかった人にも分かりやすくなっていると幸いです。

社内社外問わず、どうも問題意識がサービスの提供側ほど漠然として希薄な印象なので、確認の為にメモを残しておきます。
    ※以下はあくまで私見であり、所属組織や他のメンバーとは関係ありませんが、一般論として十分な説明となっているかとは思います。
AI系技術は、ちゃんと適用分野の深い理解がないと最適に利用することは難しそうな例でもあります。

Webサイトの導線基本構造


現在の一般的なWeb上のコンテンツ閲覧と、実世界、例えば実店舗で商品を見て回ることで、Web側がが劣ることは結構ある。現物が見られないことは永遠に超えられなさそうな壁ではあるけども、
    「広範囲の俯瞰を伴う自由な導線」
これが、Webサイト全般に欠けているものかと思う。訪問者は正に「木を見て森を見ず」の状態を常に強いられるわけです。(私はこれが嫌で、あてのないWebブラウジングはしないのです。)

新着順、人気順など、決まった順番を決めつつ、カテゴリ、価格帯など、検索条件で絞って出力を見る。(まぁ、SQLのSELECT文でORDER BYとWHEREの調整をすることと一緒だが。)
    ※キーワード検索なども多少自由になった検索条件程度。文字情報が少ないコンテンツの検索の助けにはあまりならない。
さらに個々のコンテンツ同士は、各種「売り上げランキング」「個人クリック履歴」「この商品を買った人はこんな商品も買っています」等のレコメンド等の複数のリストで参照し合う。(私は他人の買っていないものを欲しがるので、どれもクリックした記憶は殆ど無い…)

加えて、各種サーチエンジンから直接個々のコンテンツにショートカットしたりもする。

これが、一般的なWebサイトの導線基本構造かと思います。

Webサイトの収納力が産む弊害


さて、ここで問題になるのは、物理空間配置に縛られないWebサイト特有の膨大な収容能力が産む弊害です。

コンテンツが数万件程度なら、ソートとカテゴリ等既存の検索条件(よくある左ペイン)だけで、例えば全検索結果の先頭の数100件で殆どのコンテンツへの導線を網羅できているかも知れませんが、コンテンツ数が、その10倍、100倍、それ以上となったらどうでしょう?

極端な話、コンテンツが数千万件ある場合には、「よくある左ペイン」だけでは殆どのコンテンツが誰も辿りつけない「死にコンテンツ」となってしまいます。

というわけで、コンテンツが多ければ多いほど、個々のコンテンツページにある、ランキングやレコメンド等のリスト表示に期待される導線拡張の役割が大きくなるわけですが…

単純に考えればお分かりの通り、まず、明らかにランキングは「導線拡張」には寄与しません。余程の外的要因が無い限り、左ペインから辿り着ける(ことのあった)コンテンツのみが残っています。このランキング表示に残っていることが原因でクリックされたりしてランキングが維持されたりもします。過去の人気コンテンツへの導線維持の機能しか果たしません。

では、通常のレコメンドリストがその役割を果たせるかというと…
難しいと言わざるを得ません。

レコメンドリスト生成には様々な手法があり、個人のクリック履歴からランダムに出力するだけの単純なものから、各コンテンツや各閲覧端末の関係を有向グラフ状に集計してそれを元に表示するような難しい物までコンテキストの深さは様々です。

しかし、誰かが訪問していないものは表示できない(※)ことに変わりはなく、導線視点で言うと、
ある時期に存在して利用された導線の維持の機能がやはり基本になります。
    (※「表示できない」というよりは、当てずっぽうになってしまうのでレコメンドとしての「精度が他の表示より)格段に落ちる」という方が正確かも。)

ここまで説明した導線だけでは、
    「登録時に新着リストに載った時期にあまりクリックされないと死にコンテンツ確定」
を避けることができません。
    ※なので、サイトによっては幾つも同じコンテンツを定期的に新規登録したりとか、意味不明なことが行われたり。。。
導線拡張だけに特化して考えると、単純にランダム表示したり、履歴の無いコンテンツまで雑な類推で出力しても、
    「なぜ今見てるコンテンツに対してこれらのコンテンツリストが出力されているのか?」
という繋がりが論理的にも直感的にも希薄であれば、訪問者が中身を見る確率・クリックする確率はそれだけ低くなってしまうと考えられます。(例:「おすすめ」というタイトルでランダム表示)

AI系技術による導線拡張


ここで逆に考えます。
    「なぜ今見てるコンテンツに対してこれらのコンテンツリストが出力されているのか?」
がある程度、訪問者とコンセンサスが取れれば、ランダムより相当見てもらえるのではないでしょうか。

例えば、
    「人気/売り上げランキング」
    「この商品を買った人はこんな商品も買っています」
等は、その並び方自体に情報があり、あまり興味がなくてもそのタイトルの下のリストの先頭が見える頃には、頭の中はその情報を受け取る準備ができていて、先頭の何個かを見て「ふ〜ん」という程度には脳まで届くと思います。興味があればスクロールしても貰えるでしょう。

しかし「おすすめ」というランダムの場合には、「おすすめ」というタイトルで、(どういう観点だろう?)
と最初は待ち構えますが、ランダムだ(もしくは、意味がわからない並び)と判ったら、基本スキップされるのではないかと予想されます。ニーズに偶然フィットしてクリックされることはあるかも知れませんが、導線の利用率は低いと思います。

つまり、超多数のコンテンツ間の十分な導線確保のためには、
  • 互いに並びが似ていないリストで
  • 見ただけで並び方がタイトルに合っているか確認可能なものを
  • できるだけ多種類
表示することが有効と考えられます。

「見ただけで並び方がタイトルに合っているか確認可能」 としたのは、複雑すぎるのもランダム(無意味)と取られるからです。各リストのタイトルも重要と思われます。

という文脈でいうと、
レコメンドと称して履歴から何らかの範囲のランキングを表示するいう枠組みだけでは、複雑な方法でも異なるリストをそう何個も生成できない(&タイトルを決められない)ので、別の観点のリスト生成法があると(全コンテンツに行き渡るような)導線の拡張にとても有効です。

そこで、AI系技術による何らかの特徴量抽出&類似性ランキングで整理することにより、お手軽に導線拡張ができます。例えば、画像を何らかのベクトルに変換するものを使ってトップ画像の類似性ランキングを各コンテンツ基準で生成して「似た画像の商品」みたいなタイトルを付けて表示するだけで、並びにある程度の納得性があれば、意外と見てもらえると思います。

違う学習済みモデルでも同じようにやってみて、その数種の画像類似リストの観点にそれぞれふさわしいタイトルをつけて差別化することができれば、それだけで導線がかなり増やせるわけです。

画像に内容の特徴がそれほど現れないテキストメインのコンテンツでも、リストに並べたタイトル等に納得性があれば、「似た内容の記事」みたいなタイトルでリスト表示しても良いと思いますが、画像ほどの直感的説得力は無いかも知れません。

下手に混合するよりも、単純化して納得できるタイトルのリストに分離したほうが訪問者に伝わりやすいでしょう。

    ※余談
    と言う状況ですので、コンテンツが非常に多いサイトの場合には、導線拡張の効果(コスパ?)は「似た画像」リストのほうが「レコメンド」リストよりも高くなると考えられ、導入の優先順位はその特徴量類似ランキングの方が高くなるでしょう。このように導線拡張を既に他手法で行った状態をベースに追加でレコメンドの効果・導入コストが語られるようになると、現状のレコメンド手法選びは大きく変わる可能性があるので注意が必要です。(別路線の導線拡張にそれでも特化するか、追加導線拡張を諦めて純粋なレコメンドに特化するか。。。いずれにせよ、似た画像軸という落とし所を奪われた状態でのレコメンドリスト生成のハードルはかなり上がるのではないかと。)
    そして、私がこの記事を書いている現在在席しているサイジニアでは、上記のレコメンドリストの提供サービスを事業の一つとしています。加えて、画像の特徴量ベースにしたリスト毎日生成もサービスラインナップに加えているので、自分では特徴量類似性ベースのリストをですぐには試せないサイトさんは試験導入してみても良いかも知れません。

その先のコンテンツブラウズ導線の模索


前述の余談にあるような、
    直感的納得度の高い特徴量空間を持つAI系の学習済みモデルが一般的に利用されることによる、Webサイト周りの関連事業の技術再編可能性
については私は専門じゃないので語れませんが、コンテンツブラウズへのAI系技術利用を既存の「タイトル付きリスト羅列」からもう少し深めるトライアルは行っています。

つまり、冒頭で述べた、
「広範囲の俯瞰を伴う自由な導線」
の一部的でも、この特徴量空間を利用して上手く提供できないかというものです。

画像で旅する https://trip.deqwas.net
というサイトを立ち上げています。

とりあえずは、リストの後半ほど意図的により遠くの特徴的なコンテンツをピックアップすることで、少しでも俯瞰範囲を広めようとしています。

この興味深い使い心地を言語化するのが今度は難しくなってしまうのですが、真似してやってみるでもいいので、新しいインターフェースの可能性を拡散して皆で議論していきたいです。

Webサイトに限らず、個人の画像ライブラリをデータベース化して閲覧するツールなんか作ってみて公開するほうが分かりやすいでしょうか?

いつか時間ができたら…
DBの一般機能として超多次元ベクトルが扱えるようになったら、サンプルとして作ってみるとか?

ではまた。