rsRand() 显着减慢了 RenderScript

rsRand() significantly slows down RenderScript

我一直在摸不着头脑,我唯一可以得出的结论是 rsRand() 没有在通常用于 运行 脚本的处理器上实现(例如 GPU 或 CPU) 或者它不能 运行 并行。

谁能证实这一点?如果是这样,是否有参考资料列出哪些功能可以安全使用与性能相关?

有没有其他不使用rsRand()获取随机数的方法?

这是我的渲染脚本文件:

#pragma version(1)
#pragma rs java_package_name(com.example.app)
#pragma rs_fp_relaxed

float width;
float height;
float3 p0, p1, p2, p3;

uchar4 __attribute__((kernel)) gradGen(uint32_t x, uint32_t y)
{
  float3 result;
  float hd = x / width;
  float vd = y / height;
  float noise = rsRand((float) 1 / 256) - ((float) 1 / 512); // CULPRIT
  hd = 3 * hd * hd - 2 * hd * hd * hd;
  vd = 3 * vd * vd - 2 * vd * vd * vd;
  result.r = (1 - vd) * ((1 - hd) * p0.r + hd * p1.r) + vd * ((1 - hd) * p3.r + hd * p2.r) + noise;
  result.g = (1 - vd) * ((1 - hd) * p0.g + hd * p1.g) + vd * ((1 - hd) * p3.g + hd * p2.g) + noise;
  result.b = (1 - vd) * ((1 - hd) * p0.b + hd * p1.b) + vd * ((1 - hd) * p3.b + hd * p2.b) + noise;
  return rsPackColorTo8888(result);
}

与其疑惑,我决定做些蠢事,自己写 rsRand()Xorshift was simple enough and here is extra code for implementing a PRNG:

uint32_t r0 = 0x6635e5ce, r1 = 0x13bf026f, r2 = 0x43225b59, r3 = 0x3b0314d0;

uchar4 __attribute__((kernel)) gradGen(uint32_t x, uint32_t y)
{
  ...
  // Generate a random number between 0-1
  uint32_t t = r0 ^ (r0 << 11);
  r0 = r1; r1 = r2; r2 = r3;
  r3 = r3 ^ (r3 >> 19) ^ t ^ (t >> 8);
  float rnd = (float) r3 / 0xffffffff;
  ...
}

上面的速度很快,而且随机数的质量对我的应用来说已经足够好了。我仍然有兴趣了解 rsRand() 减速背后的细节。

rsRand() 在大多数实现中调用平台 rand()(这就是它在 CPU 后端中的实现方式,我不知道任何 RS GPU 驱动程序实际上在他们的驱动程序),因此它将比简单的移位和 XOR 之类的东西更重量级和更慢。

是的,看看 rand() 的仿生实现,你是对的,它是序列化的。也许我会找人移植梅森扭曲器。