私はスレッドに不慣れであり(以下の実装で私を殺さないでください:)、別のスレッドでピクセルの複数のブラーパスを実行する必要があります(以下を参照)。これはボックスブラーの最も効率的な実装ではありませんが(ConvolveOpを使用しないガウスフィルターからのものです)、パフォーマンスの急上昇はNexus 7タブレットでは発生しませんが、Nexus4電話では発生します。
テストサンプルを投稿しました(Android 4.2で実行-以下を参照)。
GCがメモリをスラッシングしたことが原因ではないと思います(スパイクとは一致しません)。
キャッシュの局所性やハードウェアメモリのスラッシングと関係があるのではないかと思いますが、よくわかりません。
スパイクの原因は何ですか?時々それらは突然発症します-例えば50%のスパイク。時々、それらはゆっくりと開始します-例えば、スパイクは単調に増加/減少し、スパイクは次のようになります-> 5%、10%、20%、10%、5%。
重い配列処理を行うときにそれらが発生するのを防ぐにはどうすればよいですか?
これは、私もテストしたNexus 7タブレットでは発生しません(以下の結果を参照)
副次的な質問:スレッドを正しくスリープおよび再起動する(スレッドを初めて使用する)ための最良の方法は何ですか?
MainActivity.java
package com.example.test;
import android.os.Bundle;
import android.app.Activity;
public class MainActivity extends Activity {
private MainThread thread;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
thread = new MainThread();
thread.setRunning(true);
thread.start();
setContentView(R.layout.activity_main);
}
@Override
protected void onResume() {
super.onResume();
thread.setRunning(true);
}
@Override
protected void onPause() {
super.onPause();
thread.setRunning(false);
}
}
MainThread.java
package com.example.test;
import android.util.Log;
public class MainThread extends Thread {
int[] pixels;
int kernel_rows = 2;
int kernel_cols = 2;
int width = 512;
int height = 512;
@Override
public void run() {
while (running) {
long start = System.currentTimeMillis();
for (int row = kernel_rows / 2; row < height - kernel_rows / 2; row++) {
for (int col = kernel_cols / 2; col < width - kernel_cols / 2; col++) {
float pixel = 0;
// iterate over each pixel in the kernel
for (int row_offset = 0; row_offset < kernel_rows; row_offset++) {
for (int col_offset = 0; col_offset < kernel_cols; col_offset++) {
// subtract by half the kernel size to center the
// kernel
// on the pixel in question
final int row_index = row + row_offset
- kernel_rows / 2;
final int col_index = col + col_offset
- kernel_cols / 2;
pixel += pixels[row_index * width + col_index] * 1.0f / 4.0f;
}
}
pixels[row * width + col] = (int) pixel;
}
}
long stop = System.currentTimeMillis();
long delta = stop - start;
Log.d("DELTA", Long.toString(delta));
}
}
private boolean running;
public void setRunning(boolean running) {
this.pixels = new int[512 * 512];
this.running = running;
}
}
ログ
Nexus 4電話(ミリ秒):
01-13 10:56:05.663: D/DELTA(13507): 76
01-13 10:56:05.773: D/DELTA(13507): 107
01-13 10:56:05.843: D/DELTA(13507): 77
01-13 10:56:05.923: D/DELTA(13507): 75
01-13 10:56:06.053: D/DELTA(13507): 127
01-13 10:56:06.133: D/DELTA(13507): 78
01-13 10:56:06.213: D/DELTA(13507): 81
01-13 10:56:06.293: D/DELTA(13507): 80
01-13 10:56:06.353: D/DELTA(13507): 77
01-13 10:56:06.433: D/DELTA(13507): 79
01-13 10:56:06.513: D/DELTA(13507): 79
01-13 10:56:06.624: D/DELTA(13507): 106
01-13 10:56:06.694: D/DELTA(13507): 76
Nexus 7タブレット(ミリ秒):
01-13 11:01:03.283: D/DELTA(3909): 84
01-13 11:01:03.373: D/DELTA(3909): 85
01-13 11:01:03.453: D/DELTA(3909): 85
01-13 11:01:03.543: D/DELTA(3909): 84
01-13 11:01:03.623: D/DELTA(3909): 85
01-13 11:01:03.703: D/DELTA(3909): 84
01-13 11:01:03.793: D/DELTA(3909): 85
01-13 11:01:03.873: D/DELTA(3909): 84
01-13 11:01:03.963: D/DELTA(3909): 85
01-13 11:01:04.043: D/DELTA(3909): 84