我的算法很容易进行聚类,就像这样。
第一个对象按所有其他对象分组,它们之间的距离低于X. 然后我们转到第二个对象,如果没有包含在第一个组中,我们对第一个组中未包含的其他对象运行相同的算法, 等等...
我正在尝试使用片段着色器在GPU中执行此算法。 首先,我将所有位置设置为RGBA浮动纹理。为每个像素设置位置(x,y) - z和w现在是免费的。然后我使用着色器绘制结果纹理我的计算。最后,我将读取结果纹理的像素并执行我的代码。
尝试了许多代码变体,多阶段绘制用于执行我的算法,但我对时间表现不满意。
问题是, 有没有办法在纹理上运行一个来执行我的愿望(单一绘制阶段)?
我最近的尝试是这个算法 - 我的片段着色器
precision highp float;
uniform sampler2D locs;
varying vec2 coord;
uniform float clusterDistance;
const float textureSize = 64.;
void main()
{
// Getting my location
vec4 currData = texture2D(locs, coord);
float offsetPix = 1./textureSize/2.;
vec2 coordIdx = (coord - offsetPix) * textureSize;
// Getting the index of my location
float myIdx = coordIdx.y * textureSize + coordIdx.x;
int clusterIdx = 0;
float clusterNum = 0.;
// Running over all the other locations until me and finding the first close object to me
for (float i=0.;i<textureSize*textureSize;++i)
{
clusterNum = i +1.;
// Which mean that we didn't find any closed object to me so we stop
if (i == myIdx)
{
break;
}
else
{
vec2 pntLoc = vec2(mod(i, textureSize), floor(i/textureSize)) / textureSize+offsetPix;
vec4 pnt = texture2D(locs, pntLoc);
if (distance(currData.xy, pnt.xy) <= clusterDistance)
{
break;
}
}
}
// Print the result
gl_FragColor = vec4(currData.x, currData.y, clusterNum, 1.);
}
但问题在于结果会导致链聚类。对于前者 如果我们的数据是{0,0},{4,0},{8,0},并且到组的最大距离是4.那么第一个关闭到第二个。然后第三个接近第二个但不是第一个。根据我的算法,它返回第二个的索引,虽然第二个是在图片之外,因为按第一个对象分组,第一个是距离的参考对象。
写入时可以从结果纹理中读取吗?
它会解决我的问题,因为我可以在比较距离时检查结果的z值。
答案 0 :(得分:0)
不,你不能在相同的传递中读取和写入纹理(使用标准的WebGL,我认为根本不是你想要的)。
你的算法本质上似乎是串行的,不太适合GPU / SIMD执行,但我可能会误解你的意图。请记住,GPU可以同时为多个数据点(在这种情况下为片段/像素)运行着色器程序,不知道其他数据点的结果。 您也无法在SIMD架构上摆脱for循环。 for循环将继续迭代,尽管不会为突破它的片段编写更改。换句话说,没有速度效益。如果中断条件评估所有片段的相同值,则会有不同的故事。
您可能希望了解其他群集方式,例如k-means。