caffe2 添加自定义op

记录一些一个没有之前没有接触过caffe/caffe2的人为了添加自定义的op 到caffe2需要做的工作.

首先参考caffe2 tutorial,随便跑个op来试试,不妨以比较简单的  Accumulate_op 为例子.

这个op的作用就是计算Y=X+gamma*Y, 其中X为输入,Y为输出,gamma是参数.

跑起来这个运算所需要的代码如下:

c之后我们仿照caffe2/operators/accumultate_op.h和affe2/operators/accumultate_op.cc,仿写一个我们自己的运算atest_op.h和atest_op.cc

实现的功能为Y=5*X+gamma*Y

之后我们编译整个caffe2,编译方式是运行pytorch/scripts/build_local.sh

编译成功后,需要将pytorch目录添加到PYTHONPATH中

然后运行

看是否成功

编译的时候可能出现mpi_test.cc.o: undefined reference to symbol ‘_ZN3MPI8Datatype4FreeEv  的报错。。解决办法是把CMakeList中的MPI关掉就好了。。。

以及。。。operators中的文件都不要删。。。本想删一些不相关的op来减少编译时间。。。想法是对的。。。但是似乎只删op是行不通的。。。。不如不删。。。不然会编译出现奇怪的错误!

不然会编译出现奇怪的错误!

不然会编译出现奇怪的错误!

以及。。。从github download的速度太慢了。。。干脆开了个40$/m的vps来搞。。。

编译成功后修改测试的python代码,来测试一下我们定义的op

发现确实是得到了Y=5*X+gamma*Y 的结果。。

撒花!(然而这只是最近要做的任务中最容易的一条线orz…

需要注意的是,运行bash build_local.sh脚本之后会在pytorch目录下生成build文件夹,下次编译的时候直接在build目录下执行make -j20,这样才是增量编译

编译的时候直接在build目录下执行make -j20,这样才是增量编译

编译的时候直接在build目录下执行make -j20,这样才是增量编译

不然每次执行build_local.sh…不知caffe2用了什么机制…每次要把所有文件编译一遍…简直没有人性啊…16个cpu一起编也要5分钟Orz

以及...要在自己定义的函数最后返回true…这样在运行的时候才不会报错.否则会报net error 的错误Orz….我好傻啊?

 

 

非极大值抑制(Non-Maximum Suppression,NMS)

 

NMS是为了在诸多CV任务如边缘检测,目标检测等,找到局部最大值

其主要思想是先设定一个阈值,然后计算检测框的IOU(所谓IOU,也就是intersection-over-union,指的是相交面积除以相并面积,是来衡量overlap程度的指数)。如果IOU大于阈值,说明overlap过大,我们要通过某种算法来将其剔除。

比如下图,在经典的人脸识别任务中,出现了多个检测框,每个检测框有一个置信度confidence,我们通过某个算法,保留一个最好的。

 

 

顺便说一下算法的实现步骤把,其实不太重要。就是贪心。

其基本操作流程如下:

  • 首先,计算每一个 bounding box 的面积:
    • (x1, y1) ⇒ 左上点的坐标,(x2, y2) ⇒ 右下点的坐标;
    • (x2-x1+1)x(y2-y1+1)
  • 根据 scores 进行排序(一般从小到大),将 score 最大的bounding box置于队列,接下来计算其余 bounding box 与当前 score 最大的 bounding box 的 IoU,抑制(忽略也即去除)IoU大于设定阈值的 bounding box;
  • 重复以上过程,直至候选 bounding boxes 为空;

 

最后上一段python代码吧…也很简单,直接转载了别人的…

 

参考链接

目标窗口检测算法-NMS非极大值抑制

reid 相关任务记录

被师兄(同事?)普及了一番实验规范orz…

我还是太年轻了

所谓的一个fc的版本是右边的.一个放着不动,另一个在sequence_len(10)的维度上做ave,然后再expand成原来的维度.如下图.

 

 

任务命名规则:

如D1V2_a_1,D1表示使用第一个数据集,V2表示是第二个大版本,a表示在V2大版本上的微调,最后的数字表示这是第几次运行该任务(跑三次以减少波动的影响)

logdir的地址为:/mnt/lustre/renkuanze/Data_t1/reid/log/{$jobname}

 

  • D1:使用ilivids 数据集
    • D1V1表示最初始的 baseline model
    • D1V2表示改为使用一个fc
      • D1V2_a是一个在一个FC上,不添加光流的修改版本
      • D1V2_b是在一个FC上的baseline版本(也就是有光流)
      • D1V2_c是在一个FC上,有光流,batchsize从32改为64,gpu数目从4改为8的版本
    • D1V3表示将softmax改为sigmod
      • D1V3_b表示将softmax改为sigmod的baseline版本
  • D2:使用prid2011数据集
    • D2V1表示初始的baseline model
    • D2V2表示改为使用一个fc
      • D2V2_b是在一个FC上的baseline版本

 

 

分类评价指标之Cumulative Match Characteristi (CMC)曲线

CMC曲线全称是Cumulative Match Characteristic (CMC) curve,也就是累积匹配曲线,同ROC曲线Receiver Operating Characteristic (ROC) curve一样,是模式识别系统,如人脸,指纹,虹膜等的重要评价指标,尤其是在生物特征识别系统中,一般同ROC曲线( 多标签图像分类任务的评价方法-mean average precision(mAP) 以及top x的评价方法)一起给出,能够综合评价出算法的好坏。

转一篇通俗易懂的解释:

Shortly speaking, imagine that you have 5 classes. For simplicity, imagine you have one test per class. Each test produces a score when compared to each class. Let’s start from test1 which belongs to class1:
As your similarity measure, here, is Euclidian distance, the more distance a test has compared to a class, the less similarity is obtained. Without loss of generality, let’s suppose that the distance measures are calibrated and normalized in terms of similarity scores.
If the score between test1 and class1 is larger than the other 4 classes (or the Euclidian distance between test1 and class1 is less than the other 4 classes), class 1 is recognized in the first rank. As an example, let’s suppose the following similarity scores (not Euclidian distances):
Test1 VS class 1= .95
Test1 VS class 2= .7
Test1 VS class 3= .9
Test1 VS class 4= .72
Test1 VS class 5= .3
What do these scores say? These similarity scores say that test 1 is more similar to class 1 than the other classes. So, test 1 is correctly recognized in the first rank.
Let’s suppose that test2, test 3, test 4 and test 5 are also recognized in the first rank.
So, we can conclude that we have a perfect CMC curve (y-x). because all of the 5 test are correctly recognized. A perfect CMC curve is as following:
Rank 1: 100%
Rank2: 100%
Rank 5:100%
Now, let’s suppose the following situation:
Test1 VS class 1= .9
Test1 VS class 2= .95
Test1 VS class 3= .4
Test1 VS class 4= .72
Test1 VS class 5= .3
What do these scores say? They say that test 1 is more similar to class 2 than class 1 (This is a mismatch and it is not correct!). So, the correct match (.9) is not the top match here (the top match is .95 which is a mismatch). In other words, test 1 is not recognized as the top match, but it is recognized among top “two matches” (the top two matches are .95 and .9). This is what rank 2 recognition means!
Now, if test 1 is recognized among top two matches but the other tests (i.e., test 2, test 3,… test 5) are recognized in the first rank (Rank 1), the first rank recognition rate is 80% (test 1 is not among the top matches, i,e, 1 out of 5 is incorrect in first rank recognition which yields 80%) but the second rank recognition rate is 100%, because all of the tests are correctly recognized among the top “two matches”. Some of them are recognized in the first rank (test 2, test 3, test 4, and test 5) while some of them are recognized in the second rank (test 1). So, the second rank recognition rate is 100%.
So, the CMC curve will be as following:
Rank1  80% (tests 2,3,4,5 are among the N=1 top matches )
Rank2 100% (tests 1,2,3,4,5 are among the N=2 top matches )
Rank3 100%  (tests 1,2,3,4,5 are among the N=3 top matches )
Rank 5 100%  (tests 1,2,3,4,5 are among the N=5 top matches )
Now, consider that test1, test 2, test 3 are recognized in the first rank, test 4 is recognized in the second rank and test 5 is recognized in the fourth rank. what is the CMC curve>? Here is the answer:
Rank 1:  60% (tests 1,2,3 are among the N=1 top matches )
Rank 2: 80% (test 1,2 ,3 ,4 are among N=2 top matches)
Rank 3: 80% (test 1,2 ,3 ,4 are among N=3 top matches)
Rank 4: 100% (test 1,2 ,3 ,4 and 5 are among N=4 top matches)
Rank 5: 100% (test 1,2 ,3 ,4 and 5 are among N=5 top matches)
Reference:
Grother, Patrick, Ross J. Micheals, and P. Jonathon Phillips. “Face recognition vendor test 2002 performance metrics.” Audio-and Video-Based Biometric Person Authentication. Springer Berlin Heidelberg, 2003.

 

 

Reid iLIDS-VID 数据集 切分

ilids-vid数据集

150个人做trainning,150个人做
在training set里面,每个人有来自两个不同camera的两段video,之后再怎么切分去train是自己的事

在bash脚本里面有两个参数,(一段比如100个frame的video里切割出很多sequence),一个参数是seq_len,是一个sequence的长度,还有一个是seq_std,是切割间隔,所以如果第一个参数是10,第二个参数是5,就会切割出来20个sequence

end-to-end 神经网络

所谓end-to-end 神经网络,更多是一种思想。

这种思想的核心是,比如对于图像处理,输入原始图像数据,输出的是直接有用的结果(有用取决于具体的任务,比如自动驾驶)

也就是尽可能少得减少人为干预,使训练是end (原始数据)  to end (对应用问题直接有用的结果)

端到端指的是输入是原始数据,输出是最后的结果,原来输入端不是直接的原始数据,而是在原始数据中提取的特征,这一点在图像问题上尤为突出,因为图像像素数太多,数据维度高,会产生维度灾难,所以原来一个思路是手工提取图像的一些关键特征,这实际就是就一个降维的过程。
那么问题来了,特征怎么提?
特征提取的好坏异常关键,甚至比学习算法还重要,举个例子,对一系列人的数据分类,分类结果是性别,如果你提取的特征是头发的颜色,无论分类算法如何,分类效果都不会好,如果你提取的特征是头发的长短,这个特征就会好很多,但是还是会有错误,如果你提取了一个超强特征,比如染色体的数据,那你的分类基本就不会错了。
这就意味着,特征需要足够的经验去设计,这在数据量越来越大的情况下也越来越困难。
于是就出现了端到端网络,特征可以自己去学习,所以特征提取这一步也就融入到算法当中,不需要人来干预了。
简单得说,符合end-to-end 的神经网络,特征应该是网络自己学习,而不是人为提取。
参考资料:

Pose-driven Deep Convolutional Model for Person Re-identification 阅读笔记

1709.08325

Reid问题指的是判断一个probe person 是否在被不同的camera捕获的gallery person 中出现。

通常是如下情景:给出一个特定camera下某个特定人的probe image 或者 video sequence,从其他camera处询问这个人的图像,地点,时间戳。

 

ReID问题至今没有很好得解决,主要原因是,不同camera下,人的姿势(pose),观察的视角(viewpoint) 变化太大了。

传统方法主要在两个大方向上努力:

  1. 用一些在图像上抽取的不变量来作为人的特征feture
  2. 去学习一个不同的距离度量方式,以至于同一个人在不同camera之间的距离尽可能小。

但是由于在实际中,行人的pose和 摄像机的viewpoint不可控,因此与之相关的feture可能不够健壮。

学习新的不同的距离度量方式需要每对camera分别计算距离,然而这是O(n^2)的时间复杂度,凉凉。

 

近些年Deep learning发展迅猛,并且在很多CV任务上表现良好。所以自然有人想把Deep learning 方法应用到Reid任务上。

目前Deep learning的做法一般分为两部分:

  • 使用softmax loss 结合person ID labels得到一个global representation
  • 首先用预定义好的body 刚体模型去得到local representation,然后将global 和local representation 融合。

目前用deep learning的方法效果已经不错了,比传统方法要好。但是目前的deep learning方法没有考虑到人的姿势(pose)的变化。

虽然目前也有些deep learning的办法在处理Reid问题时使用pose estimation algorithms 来预测行人的pose,

但是这种办法是手动完成而不是一个end-to-end(什么是end-to-end 神经网络) 的过程

所以考虑pose的潜力还没有被完全发掘。

这篇paper主要做了以下工作:

  • 提出了一种新的深层结构,将身体部分转化成相应的特征表示,以此来克服pose变化带来的问题
  • 提出了一个用来自动学习各部分权值的sub-network

这两部分工作都是end-to-end的

 

 

 

Deep Mutual Learning(相互学习) 阅读笔记

原始论文

DNN在很多问题上效果很不错,但是由于深度和宽度过大,导致需要的执行时间和内存过大。我们需要讨论一些能快速执行并且对内存的需要不大的模型。

已经有很多方法来做这件事,比较重要的是Model distillation(模型蒸馏)

基于蒸馏的模型压缩的有效性是基于一个发现:小的网络有和大的网络一样的表达能力,只不过是更难以训练找到合适的参数。

也就是说,难点在于优化(以找到合适的参数)而不在于网络的尺寸。

蒸馏的模型的做法是把一个有效的(deep or/and wide) network 作为teacher network,让一个size 较小的 student network 模仿teacher network.

这样做的好处是,size小的多的student network训练如何模仿teacher network通常要比直接训练得到目标函数容易,而效果上与teacher network相当,甚至超过teacher network.

 

在这篇paper中,作者提出了一个和蒸馏模型相关但是不同的模型: Deep Mutual Learning (相互学习,以下缩写为DML)

蒸馏模型开始于一个强大的教师网络,并通过教师网络单向(one way)教授学生网络知识。

相反,DML中,开始于一群没有经受过训练的学生网络。

具体来说,每个学生训练有两种损失:

  • 常规的监督学习损失和对齐的模仿损失
  • 每个学生的在班级中落后于其他学生的概率。

结果表明,DML的方式:比每个学生网络单独学习要好,也比传统的传统的蒸馏模型要好。

此外,我们发现,对几个tearcher network  使用 DML,要往往有更好的结果。

另外一些发现:

  • 效果随着班级中学生网络的数量的增加而增加
  • 它适用于各种网络体系结构和异构群组

关于DML为什么有效的直觉讨论:

  • 常规的监督学习损失保证每个学生单独学习时,整体上结果是越来越好的。
  • 由于初始条件不同,对下一个最可能的class的预测概率不同,这是额外信息的来源。

 

 

 

 

 

 

 

 

 

 

Similarity learning 和Metric learning

Similarity_learning

相似性学习(Similarity learning )有监督机器学习,它与回归和分类密切相关,但目标是从实例中学习一个相似函数,以衡量两个对象的相似程度或相关程度。

Similarity learning通常有四种setups:

  • regression similarity learning  在这种方式中,给出的数据是   和他们的相似度 .  目标是学习到一个函数f(x_{i}^{1},x_{i}^{2})\sim y_{i},对于 给出yi近似值。
  • Classification similarity learning  给出数据   和他们是否相似 。目标是训练出一个分类器,能够完成对一组 是否相似的二分类判断。
  • Ranking similarity learning 给出有序三元组,其中  is known to be more similar to  than to  。目标是训练出一个函数,使得对于新的三元组 ,满足。容易看出,这种方式采取了比回归更弱的监督形式,因为不需要提供精确的相似性度量,只需要提供相似性的相对顺序。因此,这种ranking-based的相似性学习更容易应用于实际的大规模应用
  • Locality sensitive hashing (LSH)   局部敏感哈希和普通哈希的不同就是,相似的项有更大的概率被放到同一个桶中。

 

顺便一提,这里有一个叫triplet loss 的概念,

这里写图片描述

如上图所示,triplet是一个三元组,这个三元组是这样构成的:从训练数据集中随机选一个样本,该样本称为Anchor,然后再随机选取一个和Anchor (记为x_a)属于同一类的样本和不同类的样本,这两个样本对应的称为Positive (记为x_p)和Negative (记为x_n),由此构成一个(Anchor,Positive,Negative)三元组。

我们发现,triplet loss 其实就是在ranking similarity learning 问题中,学习similarity function时的loss

Metric learning

相似性学习与距离度量学习密切相关。度量学习的目标是在对象上学习一个距离函数。度量或距离函数必须遵循四个公理:非负性、不可分辨的恒等式、对称性和次可加性/三角形不等式。在实际应用中,度量学习算法忽略了不可分辨物体的身份条件,学习了一个伪度量。

 

 

persion reid 论文列表

Key:

(1). Pose-driven, body part alignment, combine whole feature and body part feature, focus on alignment of part model,

(2). Combine image label and human attributes classes, do classification with attributes and identity learning

(3). Based on triplet loss, improve metric learning for an end to end learning

(4). Post-process, re-ranking

 

1. AlignedReID: Surpassing Human-Level Performance in Person Re-Identification

2. Hydraplus-net: Attentive deep features for pedestrian analysis.

3. Darkrank: Accelerating deep metric learning via cross sample similarities transfer.

4. Glad: Global-local-alignment descriptor for pedestrian retrieval.

 

  1. PDC: Pose-driven Deep Convolutional Model for Person Re-identification (ICCV2017)
  2. Spindle: Spindle Net: Person Re-identification with Human Body Region Guided Feature Decomposition and Fusion (CVPR 2017)
  3. MSML: Margin Sample Mining Loss: A Deep Learning Based Method for Person Re-identification
  4. DLPA: Deeply-Learned Part-Aligned Representation for Person Re-Identification (ICCV 2017)
  5. DTL: Deep Transfer Learning for Person Re-identification
  6. Unlabeled: Unlabeled Samples Generated by GAN Improve the Person Re-identification Baseline in vitro (ICCV 2017)
  7. In: In Defense of the Triplet Loss for Person Re-identification
  8. A: A Discriminatively Learned CNN Embedding for Person Re-identification
  9. DGD: Learning Deep Feature Representations with Domain Guided Dropout for Person Re-identification
  10. Quadruplet: Beyond triplet loss: a deep quadruplet network for person re-identification

 

1. AlignedReID: Surpassing Human-Level Performance in Person Re-Identification

2. Glad: Global-local-alignment descriptor for pedestrian retrieval.

3. Darkrank: Accelerating deep metric learning via cross sample similarities transfer.

4. Deep mutual learning

5. In Defense of the Triplet Loss fr Person Re-identification + Re-Ranking

6. Hydraplus-net: Attentive deep features for pedestrian analysis.

 

  1. MSML: Margin Sample Mining Loss: A Deep Learning Based Method for Person Re-identification
  2. In: In Defense of the Triplet Loss for Person Re-identification
  3. APR: Improving Person Re-dentification by Attribute and Identity Learning
  4. PDC: Pose-driven Deep Convolutional Model for Person Re-identification
  5. Unlabeled: Unlabeled Samples Generated by GAN Improve the Person Re-identification Baseline in vitro
  6. DTL: Deep Transfer Learning for Person Re-identification
  7. DLPA: Deeply-Learned Part-Aligned Representation for Person Re-Identification
  8. PIE: Pose Invariant Embedding for Deep Person Re-identification
  9. Re-rank: Re-ranking person re-identification with k-reciprocal encoding
  10. Spindle: Spindle Net: Person Re-identification with Human Body Region Guided Feature Decomposition and Fusion

CUDA C Best Practices Guide 阅读笔记(二) Heterogeneous Computing

CUDA 编程涉及到在不同的平台上同时运行代码:包含CPU的host 和包含GPU的device.

所以了解host和device的对性能优化是非常重要的。

2.1. Differences between Host and Device

Threading resources

host 上能同时运行的线程数目比较少(比如24个)

device上能同时运行的线程数目比较多(数量级通常为1E3,1E4等)

Threads

操作系统必须交换CPU执行通道上和下的线程以提供多线程功能。因此,上下文切换(当交换两个线程时)既慢又昂贵。

相比之下,GPU上的线程非常轻量级。在典型的系统中,成千上万的线程排队等待工作(每个线程有32个线程)。如果GPU必须等待 one warp of threads,它只需开始在另一个线程上执行工作。

简而言之,CPU内核被设计为每次最小化一个或两个线程的等待时间,而GPU被设计为处理大量并发的轻量级线程以最大化吞吐量。

RAM

host和device 各自具有各自不同的附接物理存储器。host和device内存由PCI Express ( PCIe )总线分隔,因此host内存中的项目必须偶尔通过总线传送到device内存,反之亦然

 

2.2. What Runs on a CUDA-Enabled Device?

 

下面谈谈应该把应用的哪些部分放在device 上运行

  • 大数据集上的算术运算
  • 为了获得最佳性能,设备上运行的相邻线程的内存访问应该具有一定的一致性。某些内存访问模式使硬件能够将多个数据项的读或写组合并到一个操作中。当在CUDA上的计算中使用时,无法布局以实现合并的数据,或者没有足够的局部性来有效地使用L1或纹理缓存的数据,将倾向于看到较小的加速比。
  • host和device之间的数据交换尽可能少
    • 换到device上执行的数据一定会被做足够多的运算,不然数据从Host传送到device的代价 可能与该运算在device上并行计算的优势向抵消,甚至得不偿失。
    • 数据应尽可能长时间保存在设备上。因为传输应该最小化,所以在同一数据上运行多个内核的程序应该倾向于在内核调用之间将数据保留在设备上,而不是将中间结果传输到主机,然后再将它们发送回设备进行后续计算。就是说,如果有一段连续的操作要处理某些数据,就算其中的部分操作在host上运行要比在device上快(比如不是算数运算而是逻辑处理),那么考虑到数据传输的巨大代价,将所有数据都放在device上处理可能会更好。这种处理原则即使相对较慢的内核也可能是有利的,如果它避免了一个或多个PCIe传输。

 

 

 

CMake Error at gpuxgboost_generated_updater_gpu_hist_experimental.cu.obj.Release.cmake:282 的解决办法

请教了同事…果然是身经百战见得多啊

直接告诉我cuda 8.0.27 对应版本的thrust有bug.

解决办法是从 thrust 的github搞一份最新的下来,并覆盖掉/usr/local/cuda/include/thrust/

 

CUDA C Best Practices Guide 阅读笔记(1) 并行计算方法论(APOD)

APOD指的是Assess, Parallelize, Optimize, Deploy

Assess, Parallelize, Optimize, Deploy.

如图所示,APOD过程是一个循环的过程,每次只进行一部分,从A到P到O到D,然后再进行下一轮的APOD

Assess

对于一个项目,第一步要做的是接触(Assess)项目,得到项目代码中每部分的执行时间。有了这部分内容,开发者就可以找到并行优化的瓶颈所在,并开始尝试用GPU加速。

根据Amdahl’s and Gustafson’s laws,开发者可以确定并行优化的性能上界。

Parallelize

找到瓶颈所在并确定了优化的目标和期望,开发者就可以优化代码了。调用一些如cuBLAScuFFT, or Thrust 的 GPU-optimized library  可能会很有效。

另一方面,有些应用需要开发者重构代码,以此让可以被并行优化得部分被暴露出来。

Optimize

确定了需要被并行优化的部分之后,就要考虑具体得实现方式了。

具体得实现方式通常不过只有一种,所以充分理解应用的需求是很有必要的。

要记得,APOD是一个反复迭代的过程(找到可以优化的点,实现并测试优化,验证优化效果,然后再重复)

因为对于开发者来说,没有必要最初就找到解决所有性能瓶颈的策略。

优化可以在不同的level上进行,配合性能分析工具是很有帮助的。

Deploy

大的原则是当优化完一处之后,立刻将这一部分部署到生产环境,而不是再去寻找其他可以优化的地方。

这样做有很多重要的原因,比如这会使得用户尽早从这个优化中收益(尽管提速只是部分的,但是仍然有价值)

此外,每次有改动就重新部署,也使得变化是平稳而不是激进的,这有助于减少风险。

Recommendations and Best Practice

优化根据对性能影响程度的不同有不同的优先级。

在先要处理低优先级的优化之前,一定要确保其他所有的高优先级优化都做完了。

这种方法将倾向于为所投入的时间提供最佳结果,并且将避免过早优化的陷阱。

 

需要说明的一点是,教程中的代码为了方便简洁没有关于任何 check error的部分。

在实际上这是不可取的(这不同于编写C++代码!

CUDA 7.5: 用指令级性能分析精确找到性能问题

原文:

CUDA 7.5: Pinpoint Performance Problems with Instruction-Level Profiling

 

主要是介绍了CUDA 7.5 以上的版本的 NVIDIA Visual Profiler 加入的新特性

可以细粒度到指令级,分析出性能的瓶颈(在这之前,只能分析到kernel级别)

顺便了解了一下nvidia-visual-profiler

原理大概是用PC(程序计数器)采样目前活跃的warp,然后得到这些warp的PC和状态,以此来得到更细粒度的性能分析。

Instruction-level profiling in CUDA 7.5 uses program counter (PC) sampling with a per-streaming-multiprocessor (SM) fixed-frequency sampler. At each sample period, the collector picks an active warp from the SM and captures the warp’s PC and warp state. Warp selection is performed round-robin across all active warps on the SM.

文中还给出了分析完性能瓶颈之后做出的相应优化。

下面是对一段存在内存依赖延迟(?Memory Dependency Stalls )问题的代码给出优化的过程。

我们注意到代码第一行定义了一个size为7的float类型的数组,性能分析表明这一行涉及了 LDL(“load local”)  指令,是性能的瓶颈之一。

为什么?

因为NVIDIA 的GPU 没有下标 寄存器文件,所以如果一个数组被以动态的下标访问,编译器不得不为这个数组分配local memory.

在Maxwell 架构中,local memory 没有被加入在L1 缓存中,因此访问内存会有很大的延迟。

所以为了优化这部分,就把数组拆分成相同个数的单独的变量。

然后由于没有定义成数组,因此也需要把循环展开。

优化后的代码如下: