–输入:1个query和100个Doc-title
•query经分词后的term
•每个文档的title经分词后的term
–输出:
•每个文档的title和query的特征向量四个相似度
–DNN 输入层相似度
–DNN前馈输出后相似度
–CNN输入层相似度
–CNN前馈输出后相似度
通过每一步的计算量分析(也可以用Visual Profiler), 得到:
1. CNN卷积层最耗时;
2. Word-vector从Host到Device的copy耗时大;
1. CNN卷积层优化:
因为卷积核矩阵固定,word-vector词典固定,所以每个word-vector可以事先和卷积矩阵计算好,存储起来;
存储量原来:N*100; 存储量之后:N*728*3 (N是词个数,100是词向量维度,728是卷积核个数,3个window-size)
词典增大24倍,GPU放不下,只好放到host主存;
此举:QPS800==>QPS1250
2. DNN word-vector copy优化:
把词表放到GPU,CPU端维护"offset[词id]=词在显存中的offset"的数组,把offset的mini-batch发给显存,显存上直接用GPU来Max-pooling即可;
此举:QPS1250==>QPS1400
3. CPU中的CNN卷积计算优化:
AVX2, 每个指令8个float运算;
此举:QPS1400==>QPS1600
4. 余弦相似度计算优化:
优化之前:用thrust库计算q^2, t^2, q*t, 这3个向量,然后用这个矩阵乘单位向量实现加和,最后传到host上由CPU计算余弦相似度;
分析:thurst读global-memory 4次,写3次;cuBLAS读3次写3次;
优化:手写kernel, 读2次到shared-memory,计算结果折半法reduce,直接在GPU上算完余弦相似度,写回global-memory;
此举:QPS1600==>QPS1700
题外话:
RankNet是把Query和URL-i计算一个分数s(i), Query和URL-j计算一个分数s(j),真实列表里URL-i排在URL-j的前面(且在同一个列表里),然后sigmoid(s(i)-s(j))做预测排序正确的概率,最小化交叉熵损失函数(即让预测概率尽量接近真实label)
DSSM把Query出的点击过的URL做正例,没点击的URL做负例(似乎可以不在一个列表里),负例做采样(1个正例对应5个负例),过softmax让1个正例label是1,4个负例label是0;
所以,s(i)这步,两者都是把Query和URL经过神经网络,最后一层用cosine距离计算相似分数s(i); 后面的损失函数,和正负例的选择,是不同的;