【发布时间】:2020-09-22 05:08:46
【问题描述】:
在我的 OpenCL Dijkstra 算法实现中,迄今为止最慢的部分是将一维简化图矩阵写入内核参数,即全局内存。
我的图是一个二维数组;对于 OpenCL,它会被简化为一维数组,如下所示:
for (int q = 0; q < numberOfVertices; q++)
{
for (int t = 0; t < numberOfVertices; t++)
{
reducedGraph[q * numberOfVertices + t] = graph[q][t];
}
}
放入缓冲区:
cl::Buffer graphBuffer = cl::Buffer(context, CL_MEM_READ_WRITE, numberOfVertices * numberOfVertices * sizeof(int));
设置参数需要很长时间。对于我的 5,760,000 个顶点的测试,将数据写入参数需要 3 秒以上,而算法本身需要不到 1 毫秒: p>
kernel_dijkstra.setArg(5, graphBuffer);
内核使用图作为全局参数:
void kernel min_distance(global int* dist, global bool* verticesSet, const int sizeOfChunks, global int* result, const int huge_int, global int* graph, const int numberOfVertices)
有什么办法可以加快速度吗?谢谢!
编辑:我的内核代码:
// Kernel source, calculates minimum distance in segment and relaxes graph.
std::string kernel_code =
void kernel min_distance(global int* dist, global bool* verticesSet, const int sizeOfChunks, global int* result, const int huge_int, global int* graph, const int numberOfVertices) {
for (int b = 0; b < numberOfVertices; b++) {
int gid = get_global_id(0);
int min = huge_int, min_index = -1;
for (int v = gid * sizeOfChunks; v < sizeOfChunks * gid + sizeOfChunks; v++) {
if (verticesSet[v] == false && dist[v] < min && dist[v] != 0) {
min = dist[v];
min_index = v;
}
}
result[gid] = min_index;
if (gid != 0) continue;
min = huge_int;
min_index = -1;
int current_min;
for (int a = 0; a < numberOfVertices; a++) {
current_min = dist[result[a]];
if (current_min < min && current_min != -1 && current_min != 0) { min = current_min; min_index = result[a]; }
}
verticesSet[min_index] = true;
// relax graph with found global min.
int a = 0;
int min_dist = dist[min_index];
int current_dist;
int compare_dist;
for (int i = min_index * numberOfVertices; i < min_index * numberOfVertices + numberOfVertices; i++) {
current_dist = dist[a];
compare_dist = graph[min_index * numberOfVertices + a];
if (current_dist > min_dist + compare_dist && !verticesSet[a] && compare_dist != 0) {
dist[a] = min_dist + compare_dist;
}
a++;
}
}
};
我如何入队:
numberOfComputeUnits = default_device.getInfo<CL_DEVICE_MAX_COMPUTE_UNITS>();
queue.enqueueNDRangeKernel(kernel_dijkstra, 0, cl::NDRange(numberOfVertices), numberOfComputeUnits);
【问题讨论】:
-
除非我的计算是错误的,否则 500 万个顶点应该分配一个 ~100TB 的缓冲区。这似乎有些不对劲,但如果是真的,3 秒是一个非常快的复制时间。可能另一种图形表示会是一个好主意。
标签: c++ performance opencl