@@ -1034,4 +1034,88 @@ TEST_F(SegmentationTest, ReshapeWithCrossSegmentExtent) {
10341034 executor_cache.fusion (), outputs, {t_a, t_b}, __LINE__, __FILE__);
10351035}
10361036
1037+ // Stress test: 8 segments sharing one IrContainer via segmenter container
1038+ // sharing. Exercises parallel compilation with 8 concurrent threads all
1039+ // registering vals/exprs into the same shared container.
1040+ TEST_F (SegmentationTest, SharedContainerStress8Segments) {
1041+ auto fusion = std::make_unique<Fusion>();
1042+ FusionGuard fg (fusion.get ());
1043+
1044+ // Build a linear chain with 7 segment_set boundaries → 8 segments.
1045+ // Each segment does a different pointwise op to keep them distinct.
1046+ auto tv0 = makeContigConcreteTensor ({1024 , 256 }, DataType::Float);
1047+ fusion->addInput (tv0);
1048+
1049+ auto tv = relu (tv0);
1050+ tv = segment_set (tv);
1051+ tv = neg (tv);
1052+ tv = segment_set (tv);
1053+ tv = sin (tv);
1054+ tv = segment_set (tv);
1055+ tv = relu (tv);
1056+ tv = segment_set (tv);
1057+ tv = neg (tv);
1058+ tv = segment_set (tv);
1059+ tv = sin (tv);
1060+ tv = segment_set (tv);
1061+ tv = relu (tv);
1062+ tv = segment_set (tv);
1063+ tv = neg (tv);
1064+ fusion->addOutput (tv);
1065+
1066+ auto options = at::TensorOptions ().dtype (at::kFloat ).device (at::kCUDA , 0 );
1067+ at::Tensor t0 = at::randn ({1024 , 256 }, options);
1068+
1069+ FusionExecutorCache executor_cache (std::move (fusion));
1070+ auto outputs = executor_cache.runFusionWithInputs ({t0});
1071+
1072+ FusionKernelRuntime* runtime = executor_cache.getMostRecentKernelRuntime ();
1073+ EXPECT_THAT (runtime->fusionSegments ()->groups (), SizeIs (8 ));
1074+
1075+ testValidate (executor_cache.fusion (), outputs, {t0}, __LINE__, __FILE__);
1076+ }
1077+
1078+ // Stress test: 12 parallel branches each producing a segment via independent
1079+ // reductions. Unlike the linear chain above, this creates 12 segments that
1080+ // can all compile simultaneously, maximizing concurrent lock contention on the
1081+ // shared IrContainer.
1082+ TEST_F (SegmentationTest, SharedContainerStress12ParallelBranches) {
1083+ auto fusion = std::make_unique<Fusion>();
1084+ FusionGuard fg (fusion.get ());
1085+
1086+ // 4 inputs, each feeds 3 independent reductions on different axes.
1087+ // Reductions on different axes cannot be merged → separate segments.
1088+ std::vector<TensorView*> inputs;
1089+ for (int i = 0 ; i < 4 ; i++) {
1090+ auto tv = makeContigConcreteTensor ({64 , 128 , 32 }, DataType::Float);
1091+ fusion->addInput (tv);
1092+ inputs.push_back (tv);
1093+ }
1094+
1095+ for (int i = 0 ; i < 4 ; i++) {
1096+ // Each input → 3 reductions on axes 0, 1, 2
1097+ for (int axis = 0 ; axis < 3 ; axis++) {
1098+ auto r = sum (inputs[i], {axis});
1099+ fusion->addOutput (r);
1100+ }
1101+ }
1102+
1103+ auto options = at::TensorOptions ().dtype (at::kFloat ).device (at::kCUDA , 0 );
1104+ std::vector<c10::IValue> aten_inputs;
1105+ for (int i = 0 ; i < 4 ; i++) {
1106+ aten_inputs.push_back (at::randn ({64 , 128 , 32 }, options));
1107+ }
1108+
1109+ FusionExecutorCache executor_cache (std::move (fusion));
1110+ auto outputs = executor_cache.runFusionWithInputs (aten_inputs);
1111+
1112+ FusionKernelRuntime* runtime = executor_cache.getMostRecentKernelRuntime ();
1113+ // Expect at least 6 segments (the segmenter may merge some compatible
1114+ // reductions, but incompatible reduction axes force separate segments)
1115+ EXPECT_GE (runtime->fusionSegments ()->groups ().size (), 6 );
1116+
1117+ testValidate (
1118+ executor_cache.fusion (), outputs, aten_inputs, __LINE__, __FILE__);
1119+ }
1120+
10371121} // namespace nvfuser
0 commit comments