Queue depth 增益(SSD/flash,etc)

SATA/PCIE/UFS 都支持Q的操作,即一次性发多个R/W命令。它的performance 增益并不是简单的乘以queue depth。每个queue落到die上是随机的,因此需要通过概率来统计这个值。对于Queue的增益,我们做一个简单的类比问题:假设有16辆车要过桥,每辆车过桥的时间是1秒,假如有4座桥(A,B,C,D),但这16辆车是随机上其中一座桥的,那平均一辆车过桥的时间是多少? 我们假定这个值是x,如果4座桥每次只有1辆车过桥,那16辆车过桥就要16秒,其实每辆车过桥时间是1秒。如果16辆车随机上4座桥,每辆车的过桥时间是x,那增益就是 1/x.
那现在的问题就是如何算x.
对于Ramdom read(4KB),假设map不是全部存放在DRAM中,只有一部分放在DRAM中。读map的时间假设为y,由于有一部分的map在DRAM中,map hit的概率设为H,那一笔map的读的时间就为y(1-H). 当queue depth = 1 时,一笔4KB的读,所消耗的时间为1+y(1-H).
假如queue depth 为n, 那就有n笔 data read + n笔 map read,如果die 并行的数目是4,那一共有 4n 种cases.
首先,我们需要如何罗列出这所有的排列组合:假设die A中有a 笔 data read + i 笔 map read, 组合数为 CanCin ; die B中有 b 笔 data read + j 笔 map read,组合数为 CbnaCjni ; die C中有c笔data read + k 笔 map read CcnabCknij ; Die D 中有 d 笔 data read + l 笔 map read, CddCll=1 。对于上述的排列共有:
CanCinCbnaCjniCcnabCknij,a+b+c+d=ni+j+k+l=n
上面这种排列组合所有任务完成的时间是 max(a+iy(1H),b+jy(1H),c+ky(1H),d+ly(1H)) .
对于所有的组合其增益G可以下列公式算出:
G=4n(1+y(1H))na=0ni=0nib=0nij=0nabc=0nijk=0CanCinCbnaCjniCcnabCknijmax(a+iy(1H),b+jy(1H),c+ky(1H),d+ly(1H))

这里可以用递归的方式来编程,只有1个die ->2 个die ->3 个die -> …. n 个die

#include <iostream>
#include <math.h>
using namespace std;

double gTotalServiceTime = 0; 
double gMaxServiceTime = 0;
double gCombineCount = 0; // 64bit width, overflow will happens if 32bit width
double mapDivideData = 0.542; // mapread*(1-maphit)/Dataread

//C(n,k) = A(n,k)/A(k,k)
double CombineCount(int n,int k)
{
    int i = 1;
    double temp1 = 1,temp2 =1; //using double type instead of int for avoiding overflow
    k = (k > n/2) ? (n - k) : k; //C(n,k)=C(n,n-k)
    for (i=1;i<=k;i++)
    {
        temp1 *= n-i+1;
        temp2 *=i;
    }
    temp1 /=temp2; 
    return temp1;
}
void Combine(int dataQdepth, int mapQdepth,int DieCount,double MaxServiceTime,double previousCombineCount) //previous maxservice time
{
     //cout<<"beginDataQdepth: "<<dataQdepth<<" mapQdepth: "<<mapQdepth<<" DieCount: "<<DieCount<<endl;
    double Servicetime = 0;
    if( (dataQdepth + mapQdepth) == 0 || DieCount == 1)
    {
        Servicetime = dataQdepth + (mapQdepth * mapDivideData);
        if(Servicetime > MaxServiceTime)
        {
            gMaxServiceTime = Servicetime;
        }
        gTotalServiceTime += gMaxServiceTime * previousCombineCount;
        //gCombineCount += gCurrentCombineCount;
        gCombineCount += previousCombineCount;
        //cout<<"gMaxServiceTime:"<<gMaxServiceTime<<" gCurrentCombineCount:"<<gCurrentCombineCount<<endl;
        //cout<<"return"<<endl;
        //cout<<endl;
        gMaxServiceTime = MaxServiceTime; //reset to previous die distribution max service time
        return;
    }

    for(int i = dataQdepth; i>=0;i--)
    {
        for(int j = mapQdepth; j>=0;j--)
        {
            Servicetime = i + j * mapDivideData; // this die has i data read, j map read 
           //cout<<"FordataQdepth: "<<i<<" mapQdepth: "<<j<<" Diecount: "<<DieCount<<endl;
            if(Servicetime > MaxServiceTime)
            {
                 gMaxServiceTime = Servicetime;
            }
            //cout<<"Servicetime: "<<Servicetime<<" gMaxServiceTime: "<<gMaxServiceTime<<endl;
            double dataCombine = CombineCount(dataQdepth,i);
            double mapCombine = CombineCount(mapQdepth,j);
            double Allcombine = dataCombine*mapCombine;
            previousCombineCount *= Allcombine;
            //cout<<" dataCombine: "<<dataCombine<<" mapCombine: "<<mapCombine<<" Allcombine: "<<Allcombine<<endl; 
            Combine(dataQdepth-i,mapQdepth-j,DieCount-1,gMaxServiceTime,previousCombineCount);
            previousCombineCount /= Allcombine;
        }
    }

}



void main()
{
    //read
    int dataQdepth = 32 ;
    int mapQdepth = dataQdepth;
    double CommandServiceTime = dataQdepth*(1+mapDivideData);

    //write
    /*int dataQdepth = 0; int mapQdepth = 32; double CommandServiceTime = mapQdepth*mapDivideData;*/

    int DieCount = 4;
    cout<<"dataQdepth:"<<dataQdepth<<" mapQdepth: "<<mapQdepth<<" DieCount: "<<DieCount<<endl;
    Combine(dataQdepth,mapQdepth,DieCount,0,1);
    cout<<"\ngTotalServiceTime:"<<gTotalServiceTime<<" gCombineCount: "<<gCombineCount<<" gMaxServiceTime: "<<gMaxServiceTime<<endl;
    double averagetime = gTotalServiceTime/gCombineCount;
    double gainfactor = CommandServiceTime/averagetime;
    cout<<"gain facotor:"<<gainfactor<<" averagetime: "<<averagetime<<" CommandServiceTime: "<<CommandServiceTime<<endl;

}

你可能感兴趣的:(性能,Flash,C语言,SSD,概率)