@@ -44,6 +44,8 @@ float lambda = 0.95f; // GAE lambda
4444float old_models_train = 0 .2f ; // Percent of old models
4545int count_cached_old_models = 100 ; // old_models_train * ((float)count_bots / 2.f)
4646
47+ int warmup_index = 0 ;
48+
4749ActorCritic ac_update;
4850ActorCritic ac_work;
4951std::shared_ptr<torch::optim::Adam> opt;
@@ -55,11 +57,11 @@ std::vector<int> input_to_model_id;
5557bool graph_recorded = false ;
5658
5759// Tested CUDA Graphs - produce numerical instability
58- // std::vector<torch::Tensor> graph_input_tensors;
59- // std::vector<torch::Tensor> graph_output_tensors;
60- // torch::Tensor graph_main_input_tensor, graph_main_output_tensor;
61- // at::cuda::CUDAGraph graph;
62- // at::cuda::CUDAStream graph_stream = at::cuda::getStreamFromPool();
60+ std::vector<torch::Tensor> graph_input_tensors;
61+ std::vector<torch::Tensor> graph_output_tensors;
62+ torch::Tensor graph_main_input_tensor, graph_main_output_tensor;
63+ at::cuda::CUDAGraph graph;
64+ at::cuda::CUDAStream graph_stream = at::cuda::getStreamFromPool();
6365
6466VT states;
6567VT actions;
@@ -120,8 +122,17 @@ ModelManager::ModelManager(bool is_training, std::string train_folder, size_t ba
120122 ac_update->Initialize (n_in, n_out, h_start, std_dev);
121123 ac_work->Initialize (n_in, n_out, h_start, std_dev);
122124
123- // graph_main_input_tensor = torch::empty({(int)(count_bots - old_bots_indexes.size()), n_in}, torch::kCUDA);
124- // graph_main_output_tensor = torch::empty({(int)(count_bots - old_bots_indexes.size()), n_out}, torch::kCUDA);
125+ graph_input_tensors.clear ();
126+ graph_output_tensors.clear ();
127+ for (size_t i = 0 ; i < old_bots_indexes.size (); i++)
128+ {
129+ torch::Tensor empty_in = torch::empty ({1 , n_in}, torch::kCUDA );
130+ graph_input_tensors.push_back (empty_in);
131+ torch::Tensor empty_out = torch::empty ({1 , ac_work->n_out }, torch::kCUDA );
132+ graph_output_tensors.push_back (empty_out);
133+ }
134+ graph_main_input_tensor = torch::empty ({(int )(count_bots - old_bots_indexes.size ()), n_in}, torch::kCUDA );
135+ graph_main_output_tensor = torch::empty ({(int )(count_bots - old_bots_indexes.size ()), ac_work->n_out }, torch::kCUDA );
125136
126137 // Global Speedups
127138 // Produce nondetermenistic behavior even on the same gpu
@@ -339,6 +350,7 @@ torch::Tensor sample_bernoulli_batch(torch::Tensor probs)
339350torch::Tensor process_old_model_batch (torch::Tensor outputs)
340351{
341352 // Split tensor components
353+ // printf("000\n");
342354 auto angle_logits = outputs.slice (1 , 0 , 2 );
343355 auto dir_logits = outputs.slice (1 , 2 , 5 );
344356 auto hook_logits = outputs.slice (1 , 5 , 6 );
@@ -462,17 +474,15 @@ std::vector<ModelOutput> ModelManager::Decide(
462474 {
463475 if (!input_to_model_id.empty () && input_to_model_id[i] != -1 )
464476 {
465- /* if(!graph_recorded)
466- graph_input_tensors.push_back(state_gpu[i].reshape({1, n_in}));
467- else*/
468- old_states.push_back (state_gpu[i].reshape ({1 , n_in}));
477+ graph_input_tensors[graph_counter].copy_ (state_gpu[i].reshape ({1 , n_in}), true );
478+ // old_states.push_back(state_gpu[i].reshape({1, n_in}));
469479 old_indices.push_back (i); // Track the original index
470480 graph_counter += 1 ;
471481 }
472482 else
473483 {
474- // current_states [graph_main_counter].copy_(state_gpu[i].reshape({1, n_in}), true);
475- current_states.push_back (state_gpu[i].reshape ({1 , n_in}));
484+ graph_main_input_tensor [graph_main_counter].copy_ (state_gpu[i].reshape ({n_in}), true );
485+ // current_states.push_back(state_gpu[i].reshape({1, n_in}));
476486 current_indices.push_back (i); // Track the original index
477487 graph_main_counter += 1 ;
478488 }
@@ -481,71 +491,58 @@ std::vector<ModelOutput> ModelManager::Decide(
481491
482492 // old_batches.resize(old_indices.size());
483493
484- // Vector to hold the futures
485- // std::vector<std::future<void>> futures;
486- // printf("1\n");
487- // // Process each index asynchronously
488- // for(size_t i = 0; i < old_indices.size(); ++i)
489- // {
490- // // Launch a task asynchronously
491- // futures.push_back(std::async(std::launch::async, [&, i]() {
492- // cudaSetDevice(0);
493- // at::Stream stream = at::cuda::getStreamFromPool(); // Create stream for this thread
494- // at::cuda::CUDAStreamGuard guard(stream); // Guard the stream in this scope
495- // int model_id = input_to_model_id[old_indices[i]]; // Get the model ID for this input
496- // auto av_old = old_ac[model_id]->actor_forward(state_gpu[old_indices[i]]);
497- // old_batches[old_indices[i]] = av_old; // Store the result for this old model
498- // }));
499- // }
500- // printf("2\n");
501- // if(old_indices.size())
502- // {
503- // Sleep(1000);
504- // printf("2.1\n");
505- // }
506-
507- // // Wait for all tasks to complete
508- // for(auto &future : futures)
509- // {
510- // future.get();
511- // }
512- // printf("3\n");
513-
514494 auto now = std::chrono::high_resolution_clock::now ();
515495 time_pre_forward = std::chrono::duration<double >(now - measure_time).count () * 1000 .;
516496
517497 measure_time = std::chrono::high_resolution_clock::now ();
518- torch::Tensor main_input = torch::cat (current_states, 0 );
498+ // torch::Tensor main_input = torch::cat(current_states, 0);
519499 // std::cout << graph_main_input_tensor.sizes() << std::endl;
520500
521- // Process old models
522- // cudaStreamCreate(&stream);
523- // omp_set_num_threads(4) ;
524- // #pragma omp parallel for
501+ if (!graph_recorded && warmup_index >= 3 )
502+ {
503+ torch::StreamGuard stream_guard{graph_stream} ;
504+ graph. capture_begin ();
525505
526- // graph_main_output_tensor.copy_(ac_work->actor_forward(graph_main_input_tensor), true);
506+ graph_main_output_tensor.copy_ (ac_work->actor_forward (graph_main_input_tensor), true );
527507
528- // for(int i = 0; i < graph_input_tensors.size(); ++i)
529- // {
530- // int model_id = input_to_model_id[old_indices[i]]; // get the model id for this input
531- // auto av_old = old_ac[model_id]->actor_forward(graph_input_tensors[i]);
532- // graph_output_tensors[i].copy_(av_old.reshape({n_out}), true); // store the result for this old model
533- // }
508+ for (int i = 0 ; i < graph_input_tensors.size (); ++i)
509+ {
510+ int model_id = input_to_model_id[old_indices[i]]; // get the model id for this input
511+ auto av_old = old_ac[model_id]->actor_forward (graph_input_tensors[i]);
512+ graph_output_tensors[i].copy_ (av_old.reshape ({1 , ac_work-> n_out }), true ); // store the result for this old model
513+ }
534514
535- // nvtxRangePushA("Graph begin");
515+ graph.capture_end ();
516+ graph_recorded = true ;
517+ }
518+ else if (!graph_recorded && warmup_index < 3 )
519+ {
520+ graph_main_output_tensor.copy_ (ac_work->actor_forward (graph_main_input_tensor), true );
536521
522+ for (int i = 0 ; i < graph_input_tensors.size (); ++i)
523+ {
524+ int model_id = input_to_model_id[old_indices[i]]; // get the model id for this input
525+ auto av_old = old_ac[model_id]->actor_forward (graph_input_tensors[i]);
526+ graph_output_tensors[i].copy_ (av_old.reshape ({1 , ac_work->n_out }), true ); // store the result for this old model
527+ }
528+ warmup_index += 1 ;
529+ }
530+ else
531+ {
532+ graph.replay ();
533+ }
537534
538- torch::Tensor av_current = ac_work->actor_forward (main_input);
535+ // torch::Tensor av_current = ac_work->actor_forward(main_input);
539536
540537 // printf("2.1\n");
541- // Step 2: Record the forward pass into the graph
542- // Define the kernel parameters for the forward pass using the model
543- for (int i = 0 ; i < old_states.size (); ++i)
544- {
545- int model_id = input_to_model_id[old_indices[i]]; // get the model id for this input
546- auto av_old = old_ac[model_id]->actor_forward (old_states[i]);
547- old_batches.push_back (av_old.reshape ({1 , ac_work->n_out })); // store the result for this old model
548- }
538+ // // Step 2: Record the forward pass into the graph
539+ // // Define the kernel parameters for the forward pass using the model
540+ // for(int i = 0; i < old_states.size(); ++i)
541+ // {
542+ // int model_id = input_to_model_id[old_indices[i]]; // get the model id for this input
543+ // auto av_old = old_ac[model_id]->actor_forward(old_states[i]);
544+ // old_batches.push_back(av_old.reshape({1, ac_work->n_out})); // store the result for this old model
545+ // }
549546 // std::cout << old_batches.size() << std::endl;
550547 now = std::chrono::high_resolution_clock::now ();
551548 time_forward = std::chrono::duration<double >(now - measure_time).count () * 1000 .;
@@ -554,16 +551,16 @@ std::vector<ModelOutput> ModelManager::Decide(
554551 // std::cout << graph_main_output_tensor[0] << std::endl;
555552 torch::Tensor av_current_sampled, old_current_sampled, old_current;
556553 // printf("1\n");
557- if (old_batches .size ())
554+ if (graph_output_tensors .size ())
558555 {
559- old_current = torch::cat (old_batches , 0 );
556+ old_current = torch::cat (graph_output_tensors , 0 );
560557 // printf("1.5\n");
561- // std::cout << old_current.sizes() << std::endl;
558+ // std::cout << old_current.sizes() << std::endl;
562559 old_current_sampled = process_old_model_batch (old_current);
563560 }
564561 // printf("1.5\n");
565562
566- av_current_sampled = process_main_network (av_current );
563+ av_current_sampled = process_main_network (graph_main_output_tensor );
567564 // nvtxRangePop();
568565 // std::cout << av_current[0] << std::endl;
569566 // printf("2\n");
@@ -576,15 +573,15 @@ std::vector<ModelOutput> ModelManager::Decide(
576573
577574 // Combine results from old models and current model in the correct order
578575 std::vector<torch::Tensor> all_actions_sampled (input_inputs.size ()), all_actions_original (input_inputs.size ());
579- for (size_t i = 0 ; i < old_batches .size (); ++i)
576+ for (size_t i = 0 ; i < graph_output_tensors .size (); ++i)
580577 {
581578 all_actions_sampled[old_indices[i]] = old_current_sampled[i]; // Place old model results in their original positions
582- all_actions_original[old_indices[i]] = old_batches [i].reshape ({ac_work->n_out });
579+ all_actions_original[old_indices[i]] = graph_output_tensors [i].reshape ({ac_work->n_out });
583580 }
584- for (size_t i = 0 ; i < current_states .size (); ++i)
581+ for (size_t i = 0 ; i < current_indices .size (); ++i)
585582 {
586583 all_actions_sampled[current_indices[i]] = av_current_sampled[i]; // Place current model results in their original positions
587- all_actions_original[current_indices[i]] = av_current [i];
584+ all_actions_original[current_indices[i]] = graph_main_output_tensor [i];
588585 }
589586 // printf("888\n");
590587 // nvtxRangePop();
@@ -623,7 +620,7 @@ std::vector<ModelOutput> ModelManager::Decide(
623620 if (is_training && !validating)
624621 {
625622 // torch::Tensor sampled = torch::zeros({(int)input_inputs.size(), 5}, torch::kCUDA);
626- // // printf("13\n");
623+ // printf("13\n");
627624
628625 // sampled.slice(1, 0, 2).copy_(tActions.slice(1, 0, 2));
629626 // sampled.slice(1, 2, 3).copy_(directions);
@@ -749,13 +746,15 @@ void ModelManager::SaveReplays(bool& is_full)
749746 mask.push_back (1 );
750747 }
751748 }
752- for (size_t i = 0 ; i < dones.size () && old_ac.size (); i++)
753- {
754- if (dones[i] && input_to_model_id[i] != -1 )
755- {
756- input_to_model_id[i] = static_cast <int >(round (random_float () * (float )(old_ac.size () - 1 ))); // Assign to old model
757- }
758- }
749+
750+ // Reassign to new model after completion
751+ // for(size_t i = 0; i < dones.size() && old_ac.size(); i++)
752+ // {
753+ // if(dones[i] && input_to_model_id[i] != -1)
754+ // {
755+ // input_to_model_id[i] = static_cast<int>(round(random_float() * (float)(old_ac.size() - 1))); // Assign to old model
756+ // }
757+ // }
759758 // printf("2\n");
760759 // std::cout << states[0].sizes() << std::endl;
761760 // std::cout << actions[0].sizes() << std::endl;
@@ -815,6 +814,21 @@ void ModelManager::ReassignOldModels()
815814 input_to_model_id[old_bots_indexes[i]] = static_cast <int >(round (random_float () * (float )(old_ac.size () - 1 ))); // Assign to old model
816815 }
817816
817+ graph_input_tensors.clear ();
818+ graph_output_tensors.clear ();
819+ for (size_t i = 0 ; i < old_bots_indexes.size (); i++)
820+ {
821+ torch::Tensor empty_in = torch::empty ({1 , n_in}, torch::kCUDA );
822+ graph_input_tensors.push_back (empty_in);
823+ torch::Tensor empty_out = torch::empty ({1 , ac_work->n_out }, torch::kCUDA );
824+ graph_output_tensors.push_back (empty_out);
825+ }
826+ graph_main_input_tensor = torch::empty ({(int )(count_bots - old_bots_indexes.size ()), n_in}, torch::kCUDA );
827+ graph_main_output_tensor = torch::empty ({(int )(count_bots - old_bots_indexes.size ()), ac_work->n_out }, torch::kCUDA );
828+ graph_recorded = false ;
829+ graph.reset ();
830+ warmup_index = 0 ;
831+
818832 return ;
819833}
820834
@@ -894,22 +908,6 @@ void ModelManager::Update(double avg_reward, bool cache_model, bool &updated,
894908 if (!old_ac.empty ())
895909 {
896910 ReassignOldModels ();
897- // graph_input_tensors.clear();
898- // //graph_main_input_tensors.clear();
899- // graph_output_tensors.clear();
900- // for(size_t i = 0; i < old_bots_indexes.size(); i++)
901- // {
902- // torch::Tensor empty_in = torch::empty({1, n_in}, torch::kCUDA);
903- // graph_input_tensors.push_back(empty_in);
904- // torch::Tensor empty_out = torch::empty({n_out}, torch::kCUDA);
905- // graph_output_tensors.push_back(empty_out);
906- // }
907- // graph_main_input_tensor = torch::empty({(int)(count_bots - old_bots_indexes.size()), n_in}, torch::kCUDA);
908- // graph_main_output_tensor = torch::empty({(int)(count_bots - old_bots_indexes.size()), n_out}, torch::kCUDA);
909-
910- // Clean up
911- // graph.reset();
912- // graph_recorded = false;
913911 }
914912
915913 // int botes = count_bots - old_bots_indexes.size();
0 commit comments