     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;


    // Next, add each edge into the correct corresponding queue
    for (auto i = 0; i < MAX_ADJ_UNIONS_BINS; i++)
        hd_queue_info().queues[i].initialize((size_t)10000000);
        //hd_queue_info().queues[i].initialize((size_t)hd_queue_info().queue_sizes[i]*2+2);
    TM.start();
    forAllEdgesSrcDst(hornet, bin_edges {hd_queue_info, false}, load_balancing);
    TM.stop();
    TM.print("adding to queues");
    TM.reset();

    // Phase 2: run the operator on each queued edge as appropriate
    for (auto bin = 0; bin < MAX_ADJ_UNIONS_BINS; bin++) {

        if (diag_id == 0) {
            vi_begin = 0;
            ui_begin = 0;
        } else if (diag_id > 0 && diag_id < total_work) {
            vi_begin = vi_curr;
            ui_begin = ui_curr;
            vi_inBounds = (vi_curr < v_len-1);
