4040 assert_second_fit_refits_model ,
4141)
4242
43+ # Note that num_threads > 1 for BayesianPersonalizedRanking CPU training will make model training undeterministic
44+ # https://github.com/benfred/implicit/issues/710
45+ # GPU training is always underministic
46+
4347
4448@pytest .mark .parametrize ("use_gpu" , (False , True ) if HAS_CUDA else (False ,))
4549class TestImplicitBPRWrapperModel :
@@ -71,7 +75,7 @@ def dataset(self) -> Dataset:
7175 pd .DataFrame (
7276 {
7377 Columns .User : [10 , 10 , 20 , 20 ],
74- Columns .Item : [17 , 15 , 17 , 15 ],
78+ Columns .Item : [17 , 13 , 17 , 15 ],
7579 Columns .Rank : [1 , 2 , 1 , 2 ],
7680 }
7781 ),
@@ -111,7 +115,7 @@ def test_basic(
111115 use_gpu : bool ,
112116 ) -> None :
113117 base_model = BayesianPersonalizedRanking (
114- factors = 2 , num_threads = 2 , iterations = 100 , use_gpu = use_gpu , random_state = 42
118+ factors = 2 , num_threads = 1 , iterations = 100 , use_gpu = use_gpu , random_state = 42
115119 )
116120 self ._init_model_factors_inplace (base_model , dataset )
117121 model = ImplicitBPRWrapperModel (model = base_model ).fit (dataset )
@@ -130,7 +134,7 @@ def test_basic(
130134
131135 def test_consistent_with_pure_implicit (self , dataset : Dataset , use_gpu : bool ) -> None :
132136 base_model = BayesianPersonalizedRanking (
133- factors = 2 , num_threads = 2 , iterations = 100 , use_gpu = use_gpu , random_state = 42
137+ factors = 2 , num_threads = 1 , iterations = 100 , use_gpu = use_gpu , random_state = 42
134138 )
135139 self ._init_model_factors_inplace (base_model , dataset )
136140 users = np .array ([10 , 20 , 30 , 40 ])
@@ -164,7 +168,7 @@ def test_gpu_ranking_consistent_with_pure_implicit(
164168 use_gpu : bool ,
165169 ) -> None :
166170 base_model = BayesianPersonalizedRanking (
167- factors = 2 , num_threads = 2 , iterations = 100 , use_gpu = False , random_state = 42
171+ factors = 2 , num_threads = 1 , iterations = 100 , use_gpu = False , random_state = 42
168172 )
169173 self ._init_model_factors_inplace (base_model , dataset )
170174 users = np .array ([10 , 20 , 30 , 40 ])
@@ -219,7 +223,7 @@ def test_with_whitelist(
219223 use_gpu : bool ,
220224 ) -> None :
221225 base_model = BayesianPersonalizedRanking (
222- factors = 32 , num_threads = 2 , iterations = 100 , use_gpu = use_gpu , random_state = 42
226+ factors = 32 , num_threads = 1 , iterations = 100 , use_gpu = use_gpu , random_state = 42
223227 )
224228 model = ImplicitBPRWrapperModel (model = base_model ).fit (dataset )
225229 actual = model .recommend (
@@ -279,7 +283,7 @@ def test_i2i(
279283 use_gpu : bool ,
280284 ) -> None :
281285 base_model = BayesianPersonalizedRanking (
282- factors = 2 , num_threads = 2 , iterations = 100 , use_gpu = use_gpu , random_state = 1
286+ factors = 2 , num_threads = 1 , iterations = 100 , use_gpu = use_gpu , random_state = 1
283287 )
284288 self ._init_model_factors_inplace (base_model , dataset )
285289 model = ImplicitBPRWrapperModel (model = base_model ).fit (dataset )
@@ -297,8 +301,6 @@ def test_i2i(
297301 )
298302
299303 def test_second_fit_refits_model (self , dataset : Dataset , use_gpu : bool ) -> None :
300- # note that num_threads > 1 will make model training undeterministic
301- # https://github.com/benfred/implicit/issues/710
302304 # GPU training is always nondeterministic so we only test for CPU training
303305 if use_gpu :
304306 pytest .skip ("BPR is nondeterministic on GPU" )
@@ -312,7 +314,7 @@ def set_random_state() -> None:
312314 assert_second_fit_refits_model (model , dataset , set_random_state )
313315
314316 def test_dumps_loads (self , dataset : Dataset , use_gpu : bool ) -> None :
315- base_model = BayesianPersonalizedRanking (factors = 8 , num_threads = 2 , use_gpu = use_gpu , random_state = 1 )
317+ base_model = BayesianPersonalizedRanking (factors = 8 , num_threads = 1 , use_gpu = use_gpu , random_state = 1 )
316318 model = ImplicitBPRWrapperModel (model = base_model ).fit (dataset )
317319 assert_dumps_loads_do_not_change_model (model , dataset )
318320
@@ -503,8 +505,6 @@ def test_custom_model_class(self) -> None:
503505 def test_get_config_and_from_config_compatibility (
504506 self , simple_types : bool , recommend_use_gpu : tp .Optional [bool ], recommend_n_threads : tp .Optional [int ]
505507 ) -> None :
506- # note that num_threads > 1 will make model training undeterministic
507- # https://github.com/benfred/implicit/issues/710
508508 initial_config = {
509509 "model" : {"factors" : 4 , "num_threads" : 1 , "iterations" : 2 , "random_state" : 42 },
510510 "verbose" : 1 ,
0 commit comments