structCSCGRAPH { int numVertices; int* dstPtrs; // Starting incoming edge index of each vertex int* scrList; // Source vertex index of each edge }; __global__ voidbfs_kernel_csc(CSCGRAPH graph, unsignedint* level, unsignedint* visited, unsignedint currLevel){ unsigned vertexId = blockIdx.x * blockDim.x + threadIdx.x; if (vertexId < graph.numVertices) { if (level[vertexId] == 0xFFFFFFF) { // loop through its incoming edges if not visited for (int i = graph.dstPtrs[vertexId]; i < graph.dstPtrs[vertexId + 1]; i++) { unsignedint neighbor = graph.scrList[i]; if (level[neighbor] == currLevel - 1) { level[vertexId] = currLevel; *visited = 1; // flag to indicate whether reached the end of the graph break; // Only need 1 neighbor in previous level to identify the vetex is currLevel } } } } }
// Perform BFS on private frontier unsignedint i = blockIdx.x * blockDim.x + threadIdx.x; if (i < numPrevFroniter) { unsignedint vertexId = prevFroniter[i]; for (unsignedint edge = graph.scrPtrs[vertexId]; edge < graph.scrPtrs[vertexId + 1]; edge++) { unsignedint neighbor = graph.dstList[edge]; if (atomicCAS(level + neighbor, 0xFFFFFFFF, currLevel) == 0xFFFFFFFF) { // Once a new frontier node is found, unsigned currFroniterIndex = atomicAdd(&numCurrFrontier_s, 1); if (currFroniterIndex < LOCAL_FRONTIER_SIZE) { // Try to add it to the private frontier (currFrontier_s) currFrontier_s[currFroniterIndex] = neighbor; } else { numCurrFrontier_s = LOCAL_FRONTIER_SIZE; // frontier is full, stop adding new elements unsignedint currFrontierIdx = atomicAdd(numCurrFroniter, 1); currFroniter[currFrontierIdx] = neighbor; } } } }
// Copy private frontier to global frontier __syncthreads(); __shared__ unsignedint currFrontierStartIdx; // Start index of private frontier in global frontier if (threadIdx.x == 0) { currFrontierStartIdx = atomicAdd(numCurrFroniter, numCurrFrontier_s); } __syncthreads();
// Commit private frontier to global frontier for (unsignedint j = threadIdx.x; j < numCurrFrontier_s; j += blockDim.x) { unsignedint currFroniterIdx = currFrontierStartIdx + j; currFroniter[currFroniterIdx] = currFrontier_s[j]; } }