スレッドを特定のコアにバインドできます。これによりパフォーマンスが向上します (このライブラリは Linux で最適に動作します)。
OpenHFT Java スレッド アフィニティ ライブラリ
このライブラリの使用方法の実例については、affinity/src/test/java を参照してください。
V3.2.0 - テキスト構成のサポートを追加
V3.1.1 - JNA 依存関係を 4.4.0 にアップグレード
V2.0.1 - スレッドのプロセスに getThreadId を追加しました。
Java-Thread-Affinity は、JNA を使用してネイティブのスレッド処理関数へのアクセスを提供しようとします。このライブラリを最大限に活用するには、JNA をシステムにインストールする必要があります。
Java-Thread-Affinity は現在 JNA バージョン 4.4.0 に依存しており、JNA バージョン 4.4.0 は GLIBC のバージョン 2.14 以上に依存しています。ご使用のオペレーティング システムが古いもので、GLIBC のバージョンが 2011 年より前にリリースされている場合、このライブラリはネイティブ関数を呼び出すことができません。
この問題を回避するには、リポジトリをフォークし、プロジェクトのpom
ファイル内のアーティファクトjna
およびjna-platform
の<version>
タグをオーバーライドします。
sudo apt-get インストール libjna-java
sudo yum インストール jna
/proc/cpuinfo
読み取り、CPU レイアウトを決定します。それがない場合は、すべての CPU が 1 つの CPU ソケット上にあると想定されます。
ライブラリは、デフォルトで実行されていない CPU を調べることによって決定される分離された CPU を探します。つまり、16 個の CPU があるが、そのうちの 8 個が一般使用に利用できない場合 (起動時のプロセスのアフィニティによって決定されます)、それらの CPU への割り当てが開始されます。
注: このライブラリを使用するプロセスが複数ある場合は、プロセスが使用できる CPU を指定する必要があります。指定しないと、両方のプロセスに同じ CPU が割り当てられます。プロセスが使用できる CPU を制御するには、プロセスのコマンド ラインに -Daffinity.reserved={cpu-mask-in-hex} を追加します。
注: CPU 0 はオペレーティング システム用に予約されており、どこかで実行する必要があります。
https://github.com/peter-lawrey/Java-Thread-Affinity/wiki/Getting-started
https://github.com/peter-lawrey/Java-Thread-Affinity/wiki/How-it-works
http://vanillajava.blogspot.co.uk/2013/07/micro-jitter-busy-waiting-and-binding.html
Java-Thread-Affinity では、最初にいくつかの CPU を分離する必要があります。
CPU コアが分離されると、Linux スケジューラはその CPU コアを使用してユーザー空間プロセスを実行しなくなります。分離された CPU はロード バランシングに参加せず、明示的に割り当てられない限りタスクは実行されません。
システム上の 1 番目と 3 番目の CPU コア (CPU 番号は 0 から始まります) を分離するには、起動時にカーネル コマンド ラインに次のコードを追加します。
isolcpus=1,3
次の方法で CPU のロックを取得できます。
Java6では
AffinityLock al = AffinityLock . acquireLock ();
try {
// do some work locked to a CPU.
} finally {
al . release ();
}
Java 7 または 8 の場合
try ( AffinityLock al = AffinityLock . acquireLock ()) {
// do some work while locked to a CPU.
}
さらに次のようなオプションもあります
コア全体を予約できます。ハイパースレッディングを有効にしている場合は、1 つの CPU が使用され、ツイン CPU は未使用のままになります。
try ( AffinityLock al = AffinityLock . acquireCore ()) {
// do some work while locked to a CPU.
}
既存のロックを基準にしてレイアウトを選択できます。
try ( final AffinityLock al = AffinityLock . acquireLock ()) {
System . out . println ( "Main locked" );
Thread t = new Thread ( new Runnable () {
@ Override
public void run () {
try ( AffinityLock al2 = al . acquireLock ( AffinityStrategies . SAME_SOCKET ,
AffinityStrategies . ANY )) {
System . out . println ( "Thread-0 locked" );
}
}
});
t . start ();
}
この例では、ライブラリは最初のスレッドと同じソケット上の空き CPU を優先し、それ以外の場合は任意の空き CPU を選択します。
現在のスレッドIDを取得するには、次を使用します。
int threadId = AffinitySupport . getThreadId ();
現在使用されているCPUを取得できます。
int cpuId = AffinitySupport . getCpu ();
起動時のプロセスのアフィニティは、
long baseAffinity = AffinityLock . BASE_AFFINITY ;
予約可能なCPUは
long reservedAffinity = AffinityLock . RESERVED_AFFINITY ;
アフィニティを直接取得/設定したい場合は、次のようにすることができます
long currentAffinity = AffinitySupport . getAffinity ();
AffinitySupport . setAffinity ( 1L << 5 ); // lock to CPU 5.
現在のアフィニティ状態 (ライブラリで確認される) の詳細を表示するには、Linux システムで次のスクリプトを実行します。
# change to the affinity lock-file directory (defaults to system property java.io.tmpdir)
$ cd /tmp
# dump affinity state
$ for i in "$(ls cpu-*)";
do PID="$(cat $i | head -n1)"; TIMESTAMP="$(cat $i | tail -n1)";
echo "pid $PID locked at $TIMESTAMP in $i"; taskset -cp $PID;
cat "/proc/$PID/cmdline"; echo; echo
done
pid 14584 locked at 2017.10.30 at 10:33:24 GMT in cpu-3.lock
pid 14584's current affinity list: 3
/opt/jdk1.8.0_141/bin/java ...
Java スレッド アフィニティ サポート グループ
アフィニティによる違いとその使用方法に関する記事については、 http://vanillajava.blogspot.com/2013/07/micro-jitter-busy-waiting-and-binding.html
私は現在、Java のマルチスレッド プログラムにおけるデッドロック検出に関連するプロジェクトに取り組んでいます。私たちは異なるプロセッサ上でスレッドを実行しようとしているため、同じことに関するあなたの github 投稿を見つけました。 https://github.com/peter-lawrey/Java-Thread-Affinity/wiki/Getting-started 初心者のため、知識がほとんどないため、サポートが必要です。指定した CPU 番号でスレッドを実行し、待機中にスレッドを切り替える方法を知る必要があります。
// lock a cpuId
try ( AffinityLock lock = AffinityLock . acquireLock ( n )) {
}
ここで、n はスレッドを実行する CPU です。
または
// lock one of the last CPUs
try ( AffinityLock lock = AffinityLock . acquireLockLastMinus ( n )) {
}
構成ファイルに cpuId がありますが、文字列を使用して設定するにはどうすればよいですか?
try ( AffinityLock lock = AffinityLock . acquireLock ( "last" )) {
assertEquals ( PROCESSORS - 1 , Affinity . getCpu ());
}
try ( AffinityLock lock = AffinityLock . acquireLock ( "last-1" )) {
assertEquals ( PROCESSORS - 2 , Affinity . getCpu ());
}
try ( AffinityLock lock = AffinityLock . acquireLock ( "1" )) {
assertEquals ( 1 , Affinity . getCpu ());
}
try ( AffinityLock lock = AffinityLock . acquireLock ( "any" )) {
assertTrue ( lock . bound );
}
try ( AffinityLock lock = AffinityLock . acquireLock ( "none" )) {
assertFalse ( lock . bound );
}
try ( AffinityLock lock = AffinityLock . acquireLock (( String ) null )) {
assertFalse ( lock . bound );
}
try ( AffinityLock lock = AffinityLock . acquireLock ( "0" )) { // prints a warning
assertFalse ( lock . bound );
}