我一直致力于使用arrayfire模拟生物启发的神经网络的项目。我做了一些时间测试,并对我得到的结果感到失望。我决定尝试使用最快,最简单的模型之一进行定时测试,即Izhikevich模型。当我使用该模型运行新测试时,结果更糟。我正在使用的代码如下。它没有做任何花哨的事情。它只是标准矩阵代数。但是,仅对10个神经元进行单一的等式评估需要5秒钟!之后的每一站都需要大致相同的时间。
代码:
unsigned int neuron_count = 10;
array a = af::constant(0.02, neuron_count);
array b = af::constant(0.2, neuron_count);
array c = af::constant(-65.0, neuron_count);
array d = af::constant(6, neuron_count);
array v = af::constant(-70.0, neuron_count);
array u = af::constant(-20.0, neuron_count);
array i = af::constant(14, neuron_count);
double tau = 0.2;
void StepIzhikevich()
{
v = v + tau*(0.04*pow(v, 2) + 5 * v + 140 - u + i);
//af_print(v);
u = u + tau*a*(b*v - u);
//Leaving off spike threshold checks for now
}
void TestIzhikevich()
{
StepIzhikevich();
timer::start();
StepIzhikevich();
printf("elapsed seconds: %g\n", timer::stop());
}
以下是不同数量神经元的计时结果。
结果:
neurons seconds
10 5.18275
100 5.27969
1000 5.20637
10000 4.86609
增加神经元的数量似乎没有产生巨大影响。时间有点下降了。我在这里做错了吗?有没有更好的方法来使用arrayfire优化事物以获得更好的结果?
当我将v方程切换为使用v * v而不是pow(v,2)时,步骤所需的时间降至3.75762。但这仍然非常缓慢,所以发生了一些奇怪的事情。
[编辑] 我试图将处理拆分成碎片并找到新的东西。这是我现在使用的代码。
代码:
unsigned int neuron_count = 10;
array a = af::constant(0.02, neuron_count);
array b = af::constant(0.2, neuron_count);
array c = af::constant(-65.0, neuron_count);
array d = af::constant(6, neuron_count);
array v = af::constant(-70.0, neuron_count);
array u = af::constant(-20.0, neuron_count);
array i = af::constant(14, neuron_count);
array g = af::constant(0.0, neuron_count);
double tau = 0.2;
void StepIzhikevich()
{
array j = tau*(0.04*pow(v, 2));
//af_print(j);
array k = 5 * v + 140 - u + i;
//af_print(k);
array l = v + j + k;
//af_print(l);
v = l; //If this line is here time is long on second loop
//g = l; //If this is here then time is short.
//u = u + tau*a*(b*v - u);
//Leaving off spike threshold checks for now
}
void TestIzhikevich()
{
timer::start();
StepIzhikevich();
printf("elapsed seconds: %g\n", timer::stop());
timer::start();
StepIzhikevich();
printf("elapsed seconds: %g\n", timer::stop());
}
当我在没有重新分配回v的情况下运行它或将其分配给新变量g时,第一次和第二次运行的步骤时间都很小
结果:
经过秒数:0.0036143
经过秒:0.00340621
然而,当我把v = l;回来,然后第一次运行它很快,但从那时起它很慢。
结果:
经过秒数:0.0034497
经过秒:2.98624
关于导致这种情况的任何想法?
[编辑2]
我仍然不知道为什么会这样做,但是我通过在再次使用之前复制v阵列找到了一种解决方法。
代码:
unsigned int neuron_count = 100000;
array v = af::constant(-70.0, neuron_count);
array u = af::constant(-20.0, neuron_count);
array i = af::constant(14, neuron_count);
double tau = 0.2;
void StepIzhikevich()
{
//array vp = v;
array vp = v.copy();
//af_print(vp);
array j = tau*(0.04*pow(vp, 2));
//af_print(j);
array k = 5 * vp + 140 - u + i;
//af_print(k);
array l = vp + j + k;
//af_print(l);
v = l; //If this line is here time is long on second loop
}
void TestIzhikevich()
{
for (int i = 0; i < 10; i++)
{
timer::start();
StepIzhikevich();
printf("loop: %d ", i);
printf("elapsed seconds: %g\n", timer::stop());
timer::start();
}
}
现在结果如下。它第二次运行它有点慢,但现在它很快。比以前有了巨大的进步。
结果: loop:0经过秒:0.657355
循环:1秒过去:0.981287
循环:2秒过去:0.000416182
循环:3秒过去:0.000415045
循环:经过4秒:0.000421014
循环:经过5秒:0.000413339
循环:经过6秒:0.00041675
循环:7秒过去:0.000412202
循环:8秒过去:0.000473321
循环:9秒过去:0.000677432