CMSIS-NN: Created tests for original CMSIS-NN softmax q7 implementation.

pull/19/head
Christophe Favergeon 6 years ago
parent 1f87fd50c9
commit 244770716b

@ -93,6 +93,7 @@ set(TESTSRC testmain.cpp
Source/FullyConnectedBench.cpp
Source/Pooling.cpp
Source/PoolingBench.cpp
Source/Softmax.cpp
GeneratedSource/TestDesc.cpp
)

@ -0,0 +1,25 @@
#include "Test.h"
#include "Pattern.h"
class Softmax:public Client::Suite
{
public:
Softmax(Testing::testID_t id);
void setUp(Testing::testID_t,std::vector<Testing::param_t>& paramsArgs,Client::PatternMgr *mgr);
void tearDown(Testing::testID_t,Client::PatternMgr *mgr);
private:
#include "Softmax_decl.h"
Client::Pattern<int16_t> dims;
Client::Pattern<q7_t> input;
Client::RefPattern<int16_t> ref;
Client::RefPattern<q7_t> samples;
Client::LocalPattern<int16_t> output;
Client::LocalPattern<q7_t> temp;
int nbSamples;
int vecDim;
};

@ -0,0 +1,57 @@
import os.path
import itertools
import Tools
import random
import numpy as np
import scipy.special as sp
NBTESTSAMPLES = 1000
def softmax(v):
m = sp.softmax(v)
return(np.argmax(m)+1)
def writeTest(config,nb,vecDim):
dims=[]
inputsA=[]
outputs=[]
outputsSamples = []
dims.append(NBTESTSAMPLES)
dims.append(vecDim)
for _ in range(0,NBTESTSAMPLES):
va = np.random.randn(vecDim)
va = va / np.sum(va)
r = sp.softmax(va)
outputsSamples += list(r)
outputs.append(np.argmax(r)+1)
inputsA += list(va)
inputsA=np.array(inputsA)
outputs=np.array(outputs)
outputsSamples=np.array(outputsSamples)
config.writeInput(nb, inputsA,"InputA")
config.writeInputS16(nb, dims,"Dims")
config.writeReferenceS16(nb, outputs,"Ref")
config.writeReference(nb, outputsSamples,"Samples")
def writeTests(config):
writeTest(config,1,15)
PATTERNDIR = os.path.join("Patterns","NN","Softmax",)
PARAMDIR = os.path.join("Parameters","NN","Softmax")
configq7=Tools.Config(PATTERNDIR,PARAMDIR,"q7")
writeTests(configq7)

@ -62,6 +62,9 @@ def to_q7(v):
r = -0x080
return ("0x%s" % format(struct.unpack('<B', struct.pack('<b', r))[0],'02X'))
def s8(r):
return ("0x%s" % format(struct.unpack('<B', struct.pack('<b', r))[0],'02X'))
def s16(r):
return ("0x%s" % format(struct.unpack('<H', struct.pack('<h', r))[0],'04X'))
@ -141,6 +144,21 @@ class Config:
else:
return(os.path.join(self._patternDir,"Reference%d_%s.txt" % (i,self._ext)))
def refS8P(self,i,name=None):
""" Path to a reference pattern from the ID
Args:
i (int): ID to the reference pattern
Raises:
Nothing
Returns:
str : path to the file where to generate the pattern data
"""
if name:
return(os.path.join(self._patternDir,"%s%d_%s.txt" % (name,i,"s8")))
else:
return(os.path.join(self._patternDir,"Reference%d_%s.txt" % (i,"s8")))
def refS16P(self,i,name=None):
""" Path to a reference pattern from the ID
@ -376,6 +394,31 @@ class Config:
f.write("// %f\n" % v)
f.write("%s\n" % to_q7(v))
def _writeVectorS8(self,i,data):
""" Write pattern data
The format is recognized by the text framework script.
First line is the sample width (B,H or W for 8,16 or 32 bits)
Second line is number of samples
Other lines are hexadecimal representation of the samples in format
which can be read on big endian ARM.
Args:
j (int): ID of pattern file
data (array): Vector containing the data
Raises:
Nothing
Returns:
Nothing
"""
with open(i,"w") as f:
# Write sample dimension nb sample header
#np.savetxt(i, data, newline="\n", header="W\n%d" % len(data),comments ="" )
f.write("B\n%d\n" % len(data))
for v in data:
f.write("// %d\n" % v)
f.write("%s\n" % s8(v))
def writeReference(self,j,data,name=None):
if (self._ext == "f32"):
self._writeVectorF32(self.refP(j,name),data)
@ -387,6 +430,11 @@ class Config:
self._writeVectorQ7(self.refP(j,name),data)
if (self._ext == "u32"):
self._writeVectorU32(self.refP(j,name),data)
if (self._ext == "s8"):
self._writeVectorS8(self.refP(j,name),data)
def writeReferenceS8(self,j,data,name=None):
self._writeVectorS8(self.refS8P(j,name),data)
def writeReferenceS16(self,j,data,name=None):
self._writeVectorS16(self.refS16P(j,name),data)
@ -408,6 +456,8 @@ class Config:
self._writeVectorQ7(self.inputP(j,name),data)
if (self._ext == "u32"):
self._writeVectorU32(self.inputP(j,name),data)
if (self._ext == "s8"):
self._writeVectorS8(self.inputP(j,name),data)
def writeInputS16(self,j,data,name=None):
self._writeVectorS16(self.inputS16P(j,name),data)

@ -0,0 +1,6 @@
H
2
// 1000
0x03E8
// 15
0x000F

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,96 @@
#include "Softmax.h"
#include "Error.h"
#include "arm_nnfunctions.h"
#include "Test.h"
#include <cstdio>
int16_t findMaxIndex(q7_t *vec_in, int length)
{
int16_t currentIndex=0;
int16_t i=1;
q7_t currentMax=vec_in[0];
while(i<length)
{
if (vec_in[i] > currentMax)
{
currentMax = vec_in[i];
currentIndex = i;
}
i++;
}
return(currentIndex+1);
}
int16_t differences(int16_t *pa,int16_t *pb, int length)
{
int16_t d=0;
int i=0;
while(i < length)
{
if (*pa != *pb)
{
d++;
}
pa++;
pb++;
i++;
}
return(d);
}
void Softmax::test_softmax_q7()
{
const q7_t *vec_in = input.ptr();
q7_t *pTmp = temp.ptr();
int16_t *pOut = output.ptr();
int16_t maxIndex;
for(int i=0; i <this->nbSamples;i++)
{
arm_softmax_q7(vec_in, this->vecDim, pTmp );
maxIndex=findMaxIndex(pTmp,this->vecDim);
*pOut++ = maxIndex;
vec_in += this->vecDim;
}
printf("Nb diffs : %d\n",differences(ref.ptr(),output.ptr(),this->nbSamples));
ASSERT_EQ(output,ref);
}
void Softmax::setUp(Testing::testID_t id,std::vector<Testing::param_t>& paramsArgs,Client::PatternMgr *mgr)
{
switch(id)
{
case Softmax::TEST_SOFTMAX_Q7_1:
ref.reload(Softmax::REF1_S16_ID,mgr);
dims.reload(Softmax::DIMS1_S16_ID,mgr);
input.reload(Softmax::INPUT1_Q7_ID,mgr);
const int16_t *pDims=dims.ptr();
this->nbSamples = pDims[0];
this->vecDim = pDims[1];
break;
}
output.create(ref.nbSamples(),Softmax::OUTPUT_S16_ID,mgr);
temp.create(this->vecDim,Softmax::TEMP_Q7_ID,mgr);
}
void Softmax::tearDown(Testing::testID_t id,Client::PatternMgr *mgr)
{
//output.dump(mgr);
//temp.dump(mgr);
}

@ -641,6 +641,23 @@ group Root {
arm_avgpool_s8 Test 8:test_avgpool_s8
}
}
suite Softmax {
class = Softmax
folder = SoftmaxQ7
Pattern INPUT1_Q7_ID : InputA1_q7.txt
Pattern DIMS1_S16_ID : Dims1_s16.txt
Pattern REF1_S16_ID : Ref1_s16.txt
Pattern SAMPLES1_Q7_ID : Samples1_q7.txt
Output OUTPUT_S16_ID : Output
Output TEMP_Q7_ID : Temp
Functions {
arm_softmax_q7 Test 1:test_softmax_q7
}
}
}
group NN Benchmarks

Loading…
Cancel
Save