在 OJ 平台上刷题注意到一个现象,有的题用同一份代码,测试 benchmark 落点很稳定,有的在一个时间区间范围内跳跃,不太稳定。用方差描述的话叫做,benchmark 稳定方差小,不稳定方差大。
这就让我突发奇想,能否用一段代码的 benchmark 作为随机数?如果是真·随机数,那么这段代码岂不是可以用来作为随机数生成器了?
如何检验随机性?我考虑可以用 benchmark 落点概率分布来衡量。我设计了一套简陋的代码,其中调用了一些库函数 /系统函数,包括 random、usleep、malloc、free,还有 clock_gettime 用做 benchmark。循环 N 次,统计 benchmark 的所有落点,在终端输出,能够观测概率分布。代码在gist上。翻墙不便的直接贴出来
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
int main(void)
{
int i, j, k;
int dim = 11;
int num = 1024 * 1024;
int loop = 1000;
struct timespec start, end;
size_t stat[200] = { 0 };
for (k = 0; k < loop; k++) {
usleep(50000);
srandom(time(NULL));
clock_gettime(CLOCK_MONOTONIC, &start);
for (i = 0; i < num; i++) {
double *vector = malloc(dim * sizeof(double));
for (j = 0; j < dim; j++) {
vector[j] = (double) random() / RAND_MAX * 20 - 10;
}
free(vector);
}
clock_gettime(CLOCK_MONOTONIC, &end);
size_t rand_ms = (end.tv_sec - start.tv_sec)*1000 + (end.tv_nsec - start.tv_nsec)/1000000;
stat[rand_ms]++;
}
for (i = 0; i < sizeof(stat)/sizeof(*stat); i++) {
printf("[%d](%f\%):", i, 100.0 * stat[i] / loop);
for (j = 0; j < stat[i]; j++) {
putchar('-');
}
putchar('\n');
}
return 0;
}
目前循环次数为 1000,运行时间大约 4~5 分钟(机器好可以缩短到 3~4 分钟),我曾经设成 10W 次迭代跑了一个晚上。 原先预想的是,假设系统(或 runtime )稳定的话,benchmark 落点应该近似于正态分布。遗憾的是从终端输出上看,并没有达到随机的效果,但又不是收敛到一个稳定值上,分布比较离散化。
我的几点疑问:
由于仅凭终端输出,这段 C 代码在可视化上有局限,特别当样本量很大的话。Python 好的同学可以试试可视化的库。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.