     int       id = blockIdx.x * blockDim.x + threadIdx.x;
     int queue_id = id / threads_per_union;
     int thread_id = id % threads_per_union;
+    int thread_union_id = threadIdx.x % threads_per_union;
     int block_local_id = threadIdx.x;
     int stride = blockDim.x * gridDim.x;
     int queue_stride = stride / threads_per_union;

        auto dst_vtx = hornet.vertex(array[i].y);
        int srcLen = src_vtx.degree();
        int destLen = dst_vtx.degree();
        int total_work = srcLen + destLen;
        vid_t src = src_vtx.id();
        vid_t dest = dst_vtx.id();
        if (dest < src) //opt

        if (hd_queue_info().queue_sizes[bin] == 0) continue;
        if (false) { // bin == 0
            threads_per = 1;
            //TM.start();
            // forAllEdgesAdjUnionSequential(hornet, hd_queue_info().queues[bin], op, flag);
            //TM.stop();
            //TM.print("running next bin");
            //TM.reset();
        } else if (bin == 1) {
            threads_per = 8;
            forAllEdgesAdjUnionBalanced(hornet, hd_queue_info().queues[bin], op, threads_per, flag);
        } else if (bin == 2) {
            // Imbalance case, flag = 1
