[attach]3228[/attach]
如图表示的一幅图f,其中每个方格表示一个像素,如A1、A2.....A9等。我现在要做的是进行如下操作:
1):求出该图的x方向梯度值fx,求出该图的y方向梯度值fy,求出该图的xy混合梯度值fxy;
2):利用上面求出的fx,fy,fxy求出每个像素点的16个参数。
比如这里求A1的16个参数P,其中p是个16*1的矩阵。该矩阵是由一个常数矩阵A(16*16)乘以由像素点A1、A2、A3、A4的f,fx,fy,fxy组成的一个矩阵B(16*1)得到的。所以要求的每个像素点的这16个参数和其邻域点的f、fx、fy、fxy有关。比如A1的16个参数和A2、A3、A4的f,fx,fy,fxy有关,A2的16个参数和A5、A4、A6的f,fx,fy,fxy有关。
我想实现的是像素点间的并行计算,比如:并行求解A1和A2的16个参数。不是求解每个像素点的16个参数的并行计算,比如:求解A1的16个参数。但是考虑到像素点的参数求解需要其邻域的值,比如求解A1需要A2、A3、A4的值。那么不知道在对图像进行分块后,每个块的边界的值怎么算。比如:如果我在分块过程中,A1~A9被分配到一个块中,计算A1、A2、A3、A4的值可以用块内的数据,但是计算A2、A6、A7、A8、A9就必须用到其他块的数据了。像这种可以进行并行计算么?
3):如果求解出了2)中每个像素点的16个参数,假设其组成矩阵S(大小为图像大小*16,因为每个像素有16个参数);在后面的算法中要反复访问S中的数据,而且还可能出现不同块中的多个线程同时访问S中相同位置的数据的情况(这里就是说标题讲的每个线程都要对同一数据进行访问,讲的有些不确切)。这样一般怎么处理S比较好?
4):还有这样是把图像保存成1D数组还是2D数组好?
5):也不知道这次讲清楚没有,如果不够清楚,希望版主提出了我继续补充。。谢谢
LZ您好:
您的问题描述的太过笼统了,我无法直接看明白您的意图,并将此意图转化为具体算法,再给出您实现建议的。敬请谅解。
祝您好运~
楼主说的好混沌啊。。。
(1)不过看了看您的图,您的意思是在访问了A1元素后,要求对临近的A2,A3,A4,A5那些能方便的访问到,那么我建议您使用CUDA Array + 2D texture访问。这样可以取得存储上的临近性和访问上的临近性便利。
这是关于您的访问上的解答。
(2)关于您的说“处理n个数据,能否进行并行处理”这个无法回答。太笼统了。
(3)最后,您客气了。服务您是我们的荣幸。
版主你好,问题已经重新描述。。你看一下这下是否清楚,如果还有不清楚的地方。。请提出来,我好补充。。谢谢。
版主你好,问题已经重新描述。。你看一下这下是否清楚,如果还有不清楚的地方。。请提出来,我好补充。。谢谢
我重新看了您修改后的帖子,大致有如下看法:
如果结果d(x,y)的计算需要源数据s(x,y)和他附近的一些点s(x+…, y+…)那么我觉得您可以依次尝试如下:
(1)尝试每个计算结果d(x,y)的线程都依次读取s(x,y)和s(x+…, y+…)。然后您自我感觉下运行时间,看是否满意。
(2)如果您感觉不满意,建议您使用texture或者surface读取,以便利用texture cache(您可以看到,您的临近的线程将有重叠的数据读取,而且空间上有关系,不妨尝试下texture. 然后您可以对2评估下运行时间,看是否满意。
(3)如果您依然不满意,您可以考虑将一些临近的线程组成的block协作起来,将它们的一些重叠的数据放入shared memory, 以便提高利用率。然后您依然可以继续评估下您的实现。
(4)以及可能还有其他我没有指明的做法。
需要支持的是,(1)-(4)的过程不一定您会得到性能提升,这主要看2点:
(1)您的对每个点的计算量如何?如果计算量较大,已经卡在计算上了,那么您可能改善访存效率无用。
(2)以上改善还要看您的具体代码写法如何。不一定总是正面效果。
以及,如果您上去直接读取计算就满意,达到要求了,您可以完全不修改的,直接就这样交给客户也是可以的。
这是我的建议。
谢谢版主的建议,版主主要讲的是第三点吧。因为第二点中怎么并行求解每个像素点的16个参数还不是很清楚。。所以第三步还是理论上的,还没有写成代码。
1):我在把第二点说一下,我要求每个像素点对应的16个参数,比如A1~A9每个点对应16个参数,但是求解这每个像素点的16个参数和其领域像素点的灰度值和一二阶导数有关。比如求A1的16个参数,与A4、A2、A3的灰度值与一二阶导数有关,像这种我能不能并行的计算A1~A9每个像素对应的16个参数呢?
简单的讲就是我要求一个像素的对应值,但是这个对应值的求解和这个像素的邻域像素值有关系,那么我是否可以用并行计算求解每个像素点的对应值(这里的疑惑是这个值的求解和邻域有关,不知道能不能并行)
2):对于第三点还有个问题,比如我现在有n个block分别为b1、b2…bn,每个块中有512个线程,我用bi-tj表示第i个block的第j个线程。因为在程序中会出现不同线程块中的线程访问S的同一个地方的问题。比如b1-t3和b4-t8、b8-t150都要访问s中的相同元素比如s[200](这里s用一维数组表示),那么这种情况会不会出现什么访问冲突的问题?而且这里的s怎么存储才能满足不出现冲突的条件?谢谢版主!
LZ您好:
1:您这个问题无法回答。神马导数,神马参数上来一堆,一个公式都没有,更不要说离实现还有十万八千里远。这比看贵方向论文都抽象的。同时,导数是微积分中的概念,您这里面作为离散的点,必然是差分近似微分,然后求出近似的微商(导数)。而且您还要求二阶的,又不给具体格式。真心无法脑补如此多的贵专业的知识了。
如果您真有心自行判断,请将上述计算过程自己列一个依赖关系的流程表,看看每一个步骤是如何数值实现的,有哪些访存操作,那些计算操作,都梳理一遍自然就知道能否并行实现了。
2:如果您的s[200]本身是不会改变的,那么随便怎么读都可以的,不会有因果上的逻辑问题。以及不同block的线程读取这里的同一个地址并无问题。
以及,如果从读取效率出发,您可以考虑您的算法中,同一warp内的线程访问是否合并。但需要指出的是,即便访问不合并,这也只是效率问题,而不是逻辑问题。
大致如上,谨祝编码顺利,晚安~
:L好吧。。我在自己想一想。。不懂的总结过后再来请教。。
谢谢版主。。版主指导的是,我确实要求的是差分和二阶差分。。昨天晚上回去想了一下,主要还是问题2的问题,即不同block的线程对同一个地址的访问,既然无问题,那么实现就应该不困难。我今天把代码写一下,有代码说着比较方便。现在这样讲着有点太抽象,我的表达能力又一般。。表达不清楚。。道歉了。。
LZ您好:
1:对于差分和二阶差分而言,一般都是相邻两点或者多点做减法和除法操作。当使用线程排开的时候,相邻线程访存的合并性一般问题不大。以及之前横扫版主的回帖在您优化访存的时候都值得深入参考。
2:对于您说的问题2,如果s数组本身并不会被改变,那这就是一般常用的用法,各个block里面的线程直接读取即可,并不会有什么问题。因为s自身总是在显存里面的,而且是全部block可见的(当然要传参数或者是__device__定义的s),那么各个运行着的block中的线程需要s中数据的时候会请求访存,然后会按照warp为单位将这样的请求合并为一次或者多次具体的访存,并从L2 cache中拿到数据。如果L2 cache命中,那么可以较快拿到,如果不命中,需要读取一次显存的DRAM才行。
这一切都是常规的用法,不知您的顾虑何在呢?
能否明示?
祝您一切顺利~
补充下差分问题寻址的事情。
按照您之前的描述,大致上还有一个分块的问题,以及分块以后访存的问题。
如果您是使用线程索引协助访存的,那么线程索引对应到a地址的线程直接访问a+1地址也并无问题,只要注意别越界就行了。
如果您是在shared memory上使用,那么提前读入的时候可能需要将所有的可能访问的位置的数据都读进来,通俗地说,可能需要多读一圈进来。
大致补充如上,祝您好运~