Files
paddlepaddle--paddle/test/xpu/test_collective_api_base.py
2026-07-13 12:40:42 +08:00

810 lines
30 KiB
Python

# Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import pickle
import socket
import subprocess
import sys
import tempfile
import unittest
from contextlib import closing
import numpy as np
sys.path.append("../legacy_test")
from op_test import convert_float_to_uint16, convert_uint16_to_float
import paddle
import paddle.distributed as dist
from paddle import base
from paddle.base import core
def create_bool_test_data(shape=None, seed=None):
if seed:
np.random.seed(seed)
data = np.random.choice([True, False], size=shape)
return data
def create_float_test_data(shape=None, dtype=None, seed=None):
if seed:
np.random.seed(seed)
data = np.random.random(shape).astype(dtype)
return data
def create_bfloat16_test_data(shape=None, seed=None):
if seed:
np.random.seed(seed)
data = np.random.uniform(-100.0, 100.0, shape).astype("float32")
data = convert_float_to_uint16(data)
return data
def create_int_test_data(shape=None, dtype=None, seed=None):
if seed:
np.random.seed(seed)
data = np.random.randint(0, high=12, size=shape).astype(dtype)
return data
def create_complex_test_data(shape=None, dtype=None, seed=None):
if seed:
np.random.seed(seed)
data = np.random.random(shape).astype(dtype)
data.imag = np.random.random(shape)
return data
def create_pyobject_test_data(shape=None, seed=None):
if seed:
np.random.seed(seed)
list_shape = np.random.randint(0, high=100, size=(2)).tolist()
list_data = np.random.random(shape).tolist()
dict_key = list(range(0, shape[0]))
dict_val = np.random.random(shape).tolist()
dict_data = dict(zip(dict_key, dict_val))
return [list_data, dict_data]
def dump_output(x):
dump_file = os.environ['DUMP_FILE']
with open(dump_file, 'wb') as f:
pickle.dump(x, f)
def create_test_data(shape=None, dtype=None, seed=None):
assert shape, "Shape should be specified"
if dtype == "float32" or dtype == "float16" or dtype == "float64":
return create_float_test_data(shape=shape, dtype=dtype, seed=seed)
elif dtype == "bfloat16":
return create_bfloat16_test_data(shape=shape, seed=seed)
# return create_float_test_data(shape=shape, dtype=bfloat16, seed=seed)
elif dtype == "bool":
return create_bool_test_data(shape=shape, seed=seed)
elif (
dtype == "int32"
or dtype == "int64"
or dtype == "int8"
or dtype == "uint8"
):
return create_int_test_data(shape=shape, dtype=dtype, seed=seed)
elif dtype == "complex64" or dtype == "complex128":
return create_complex_test_data(shape=shape, dtype=dtype, seed=seed)
elif dtype == "pyobject":
return create_pyobject_test_data(shape=shape, seed=seed)
else:
raise NotImplementedError("Unsupported dtype for creating test data.")
class TestCollectiveAPIRunnerBase:
def get_model(
self, train_prog, startup_prog, rank, indata=None, dtype=None
):
raise NotImplementedError(
"get model should be implemented by child class."
)
def run_trainer(self, args):
train_prog = base.Program()
startup_prog = base.Program()
endpoints = args["endpoints"].split(",")
rank = args["trainerid"]
current_endpoint = args["currentendpoint"]
nranks = 2
if args['static_mode']:
paddle.distributed.collective._init_parallel_env(args["backend"])
else:
paddle.distributed.init_parallel_env()
if args['backend'] == 'nccl':
device_id = int(os.getenv("FLAGS_selected_gpus", "0"))
place = base.CUDAPlace(
device_id
) # if args.use_gpu else base.CPUPlace()
elif args['backend'] == 'bkcl':
device_id = int(os.getenv("FLAGS_selected_xpus", "0"))
place = base.XPUPlace(device_id)
else:
place = base.CPUPlace()
indata = create_test_data(
shape=(10, 1000), dtype=args["dtype"], seed=os.getpid()
)
if args['static_mode']:
result = (
self.get_model_new(
train_prog,
startup_prog,
rank,
dtype=args['dtype'],
reduce_type=args['reduce_type'],
)
if args["use_comm_context"]
else (
self.get_model(
train_prog, startup_prog, rank, dtype=args['dtype']
)
)
)
exe = base.Executor(place)
exe.run(startup_prog)
fetch_list = []
for elem in result:
fetch_list.append(elem.name)
out = exe.run(
train_prog, feed={'tindata': indata}, fetch_list=fetch_list
)
else:
out = self.get_model(train_prog, startup_prog, rank, indata)
dump_output(out)
def runtime_main(test_class, col_type):
args = {}
model = test_class()
args["trainerid"] = int(os.getenv("PADDLE_TRAINER_ID"))
args["trainernum"] = int(os.getenv("PADDLE_TRAINERS_NUM"))
args["endpoints"] = os.getenv('PADDLE_TRAINER_ENDPOINTS')
args["currentendpoint"] = os.getenv("PADDLE_CURRENT_ENDPOINT")
args["col_type"] = col_type
args["backend"] = os.getenv("BACKEND")
args["path_id"] = int(os.getenv("PATH_ID"))
args["static_mode"] = int(os.getenv("STATIC_MODE"))
args["dtype"] = os.getenv("DTYPE")
args["reduce_type"] = os.getenv("REDUCE_TYPE")
args["use_comm_context"] = bool(int(os.getenv("USE_COMM_CONTEXT", "0")))
model.run_trainer(args)
class TestDistBase(unittest.TestCase):
def setUp(self):
self._port_set = set()
self._trainers = 2
self._ps_endpoints = f"127.0.0.1:{self._find_free_port()},127.0.0.1:{self._find_free_port()}"
self._python_interp = sys.executable
self._master_endpoints = f"127.0.0.1:{self._find_free_port()}"
self.temp_dir = tempfile.TemporaryDirectory()
def tearDown(self):
self.temp_dir.cleanup()
def _find_free_port(self):
def __free_port():
with closing(
socket.socket(socket.AF_INET, socket.SOCK_STREAM)
) as s:
s.bind(('', 0))
return s.getsockname()[1]
while True:
port = __free_port()
if port not in self._port_set:
self._port_set.add(port)
return port
def _run_cluster(self, model_file, envs):
worker_endpoints = self._ps_endpoints.split(",")
w0_ep, w1_ep = worker_endpoints
if core.is_compiled_with_cuda():
env0 = {
"FLAGS_selected_gpus": "0",
"PADDLE_TRAINER_ID": "0",
"PADDLE_TRAINERS_NUM": "2",
"PADDLE_TRAINER_ENDPOINTS": self._ps_endpoints,
"PADDLE_CURRENT_ENDPOINT": w0_ep,
"PADDLE_MASTER": self._master_endpoints,
}
env1 = {
"FLAGS_selected_gpus": "1",
"PADDLE_TRAINER_ID": "1",
"PADDLE_TRAINERS_NUM": "2",
"PADDLE_TRAINER_ENDPOINTS": self._ps_endpoints,
"PADDLE_CURRENT_ENDPOINT": w1_ep,
"PADDLE_MASTER": self._master_endpoints,
}
elif core.is_compiled_with_xpu():
env0 = {
"FLAGS_selected_xpus": "0",
"PADDLE_TRAINER_ID": "0",
"PADDLE_TRAINERS_NUM": "2",
"PADDLE_TRAINER_ENDPOINTS": self._ps_endpoints,
"PADDLE_CURRENT_ENDPOINT": w0_ep,
# 'XPUAPI_DEBUG': '0x1',
}
env1 = {
"FLAGS_selected_xpus": "1",
"PADDLE_TRAINER_ID": "1",
"PADDLE_TRAINERS_NUM": "2",
"PADDLE_TRAINER_ENDPOINTS": self._ps_endpoints,
"PADDLE_CURRENT_ENDPOINT": w1_ep,
# 'XPUAPI_DEBUG': '0x1',
}
# update environment
env0.update(envs)
env1.update(envs)
cur_pid = os.getpid()
dump_file_0 = f'./out_data_0_{cur_pid}.pickled'
dump_file_1 = f'./out_data_1_{cur_pid}.pickled'
env0['DUMP_FILE'] = dump_file_0
env1['DUMP_FILE'] = dump_file_1
if os.getenv('WITH_COVERAGE', 'OFF') == 'ON':
tr_cmd = "%s -m coverage run --branch -p %s"
else:
tr_cmd = "%s %s"
tr0_cmd = tr_cmd % (self._python_interp, model_file)
tr1_cmd = tr_cmd % (self._python_interp, model_file)
path0 = os.path.join(
self.temp_dir.name, f"/tmp/tr0_err_{os.getpid()}.log"
)
path1 = os.path.join(
self.temp_dir.name, f"/tmp/tr1_err_{os.getpid()}.log"
)
tr0_pipe = open(path0, "w")
tr1_pipe = open(path1, "w")
tr0_proc = subprocess.Popen(
tr0_cmd.strip().split(),
stdout=subprocess.PIPE,
# stderr=tr0_pipe,
env=env0,
)
tr1_proc = subprocess.Popen(
tr0_cmd.strip().split(),
stdout=subprocess.PIPE,
# stderr=tr1_pipe,
env=env1,
)
tr0_out, tr0_err = tr0_proc.communicate()
tr1_out, tr1_err = tr1_proc.communicate()
sys.stderr.write(f'trainer 0 stderr: {tr0_err}\n')
sys.stderr.write(f'trainer 1 stderr: {tr1_err}\n')
# close trainer file
tr0_pipe.close()
tr1_pipe.close()
# sys.stdout.write(f'trainer 0 stdout: {tr0_out}\n')
# sys.stdout.write(f'trainer 1 stdout: {tr1_out}\n')
with open(path0, "r") as f:
sys.stderr.write(f'trainer 0 stderr file: {f.read()}\n')
with open(path1, "r") as f:
sys.stderr.write(f'trainer 1 stderr file: {f.read()}\n')
def load_and_remove(path):
with open(path, 'rb') as f:
out = pickle.load(f)
os.remove(path)
return out
return (
load_and_remove(dump_file_0),
load_and_remove(dump_file_1),
tr0_proc.pid,
tr1_proc.pid,
)
def check_with_place(
self,
model_file,
col_type,
backend="bkcl",
path_id="0",
static_mode="1",
check_error_log=False,
need_envs={},
eager_mode=True,
dtype=None,
reduce_type=None,
):
if backend == "nccl" or backend == "bkcl":
with_gloo = '0'
else:
with_gloo = '1'
required_envs = os.environ.copy()
dtype = "float32" if dtype is None else dtype
reduce_type = dist.ReduceOp.SUM if reduce_type is None else reduce_type
additional_envs = {
"NCCL_P2P_DISABLE": "1",
"STATIC_MODE": static_mode,
"PADDLE_WITH_GLOO": with_gloo,
"PADDLE_DISTRI_BACKEND": backend,
"BACKEND": backend,
"PATH_ID": path_id,
"DTYPE": dtype,
"REDUCE_TYPE": str(reduce_type),
}
required_envs.update(additional_envs)
required_envs.update(need_envs)
if check_error_log:
required_envs["GLOG_v"] = "3"
required_envs["GLOG_logtostderr"] = "1"
required_envs["GLOO_LOG_LEVEL"] = "TRACE"
if os.getenv('NVIDIA_TF32_OVERRIDE', '') is not None:
required_envs['NVIDIA_TF32_OVERRIDE'] = os.getenv(
'NVIDIA_TF32_OVERRIDE', ''
)
tr0_out, tr1_out, pid0, pid1 = self._run_cluster(
model_file, required_envs
)
input1 = create_test_data(shape=(10, 1000), dtype=dtype, seed=pid0)
input2 = create_test_data(shape=(10, 1000), dtype=dtype, seed=pid1)
# cast bfloat16 to float32 for numeric comparison
if dtype == "bfloat16":
def convertbf16(origin):
if origin.dtype == np.uint16:
return convert_uint16_to_float(origin)
else:
return origin.astype("float32")
input1 = convertbf16(input1)
input2 = convertbf16(input2)
tr0_out = [convertbf16(e) for e in tr0_out]
tr1_out = [convertbf16(e) for e in tr1_out]
if col_type == "allgather":
need_result = np.vstack((input1, input2))
tr_out0 = np.vstack((tr0_out[0], tr0_out[1]))
tr_out1 = np.vstack((tr1_out[0], tr1_out[1]))
np.testing.assert_allclose(tr_out0, need_result, rtol=1e-05)
np.testing.assert_allclose(tr_out1, need_result, rtol=1e-05)
elif col_type == "allgather_object":
need_result = [input1, input2]
self.assertEqual(need_result, tr0_out)
self.assertEqual(need_result, tr1_out)
elif col_type == "broadcast":
need_result = input2
np.testing.assert_allclose(tr0_out[0], need_result, rtol=1e-05)
np.testing.assert_allclose(tr1_out[0], need_result, rtol=1e-05)
elif col_type == "broadcast_object_list":
need_result = [input2]
self.assertEqual(need_result, tr0_out)
self.assertEqual(need_result, tr1_out)
elif col_type == "reduce":
if reduce_type == dist.ReduceOp.SUM:
need_result = input1 + input2
elif reduce_type == dist.ReduceOp.MAX:
need_result = np.amax([input1, input2], 0)
elif reduce_type == dist.ReduceOp.MIN:
need_result = np.amin([input1, input2], 0)
elif reduce_type == dist.ReduceOp.PROD:
need_result = np.prod([input1, input2], 0)
# bfloat16 precision loss comes from truncating the last 16 bits of float32,
# which sums (\sum_{i=-23}^{-8}2^{i}) to about 0.0078
if dtype == "bfloat16":
rtol = 8e-03
else:
rtol = 1e-05
np.testing.assert_allclose(tr0_out[0], need_result, rtol=rtol)
elif col_type == "scatter":
need_result = input2
need_result1 = need_result[0 : need_result.shape[0] // 2]
need_result2 = need_result[need_result.shape[0] // 2 :]
np.testing.assert_allclose(tr0_out[0], need_result1, rtol=1e-05)
np.testing.assert_allclose(tr1_out[0], need_result2, rtol=1e-05)
elif col_type == "scatter_object_list":
need_result = input2
need_result1 = [need_result[0 : len(need_result) // 2]]
need_result2 = [need_result[len(need_result) // 2 :]]
self.assertEqual(need_result1, tr0_out)
self.assertEqual(need_result2, tr1_out)
elif col_type == "gather":
# rank 0 gather all tensor
self.assertEqual(len(tr0_out), 2)
# rank 1 get nothing
self.assertEqual(len(tr1_out), 0)
# check values
np.testing.assert_equal(input1, tr0_out[0])
np.testing.assert_equal(input2, tr0_out[1])
elif col_type == "reduce_scatter":
need_result = input1 + input2
need_result1 = need_result[0 : need_result.shape[0] // 2]
need_result2 = need_result[need_result.shape[0] // 2 :]
if dtype == "bfloat16":
rtol = 8e-03
else:
rtol = 1e-05
np.testing.assert_allclose(tr0_out[0], need_result1, rtol=rtol)
np.testing.assert_allclose(tr1_out[0], need_result2, rtol=rtol)
elif col_type == "allreduce":
if reduce_type == dist.ReduceOp.SUM:
need_result = input1 + input2
elif reduce_type == dist.ReduceOp.MAX:
need_result = np.amax([input1, input2], 0)
elif reduce_type == dist.ReduceOp.MIN:
need_result = np.amin([input1, input2], 0)
elif reduce_type == dist.ReduceOp.PROD:
need_result = np.prod([input1, input2], 0)
if dtype == "bfloat16":
rtol = 8e-03
atol = 8e-03
else:
rtol = 1e-05
atol = 1e-05
np.testing.assert_allclose(
tr0_out[0], need_result, rtol=rtol, atol=atol
)
np.testing.assert_allclose(
tr1_out[0], need_result, rtol=rtol, atol=atol
)
elif col_type == "parallel_embedding":
result_data = tr0_out[0]
np.random.seed(2020)
need_result = np.random.rand(12, 8)
for i in range(result_data.shape[0]):
for j in range(result_data.shape[1]):
data = result_data[i][j]
np.testing.assert_allclose(
tr0_out[1][i][j], need_result[data], atol=1e-08
)
elif col_type == "row_parallel_linear":
result_data = tr0_out[0]
np.random.seed(2020)
weight = np.random.rand(1000, 16)
need_result = np.matmul(input1, weight)
np.testing.assert_allclose(
result_data, need_result, rtol=1e-05, atol=1e-05
)
elif col_type == "column_parallel_linear":
result_data = tr0_out[0]
np.random.seed(2020)
weight = np.random.rand(1000, 16).astype(np.float32)
need_result = np.matmul(input1, weight)
np.testing.assert_allclose(
result_data, need_result, rtol=1e-05, atol=1e-05
)
elif col_type == "dist_concat":
result_data = tr0_out[0]
need_result = np.concatenate((input1, input2), axis=1)
np.testing.assert_allclose(
result_data, need_result, rtol=1e-05, atol=1e-05
)
np.testing.assert_allclose(
result_data, need_result, rtol=1e-05, atol=1e-05
)
elif col_type in ["alltoall_single", "alltoall_tensor", "alltoall"]:
need_result1 = np.vstack(
(
input1[0 : input1.shape[0] // 2, :],
input2[0 : input2.shape[0] // 2, :],
)
)
need_result2 = np.vstack(
(
input1[input1.shape[0] // 2 :, :],
input2[input2.shape[0] // 2 :, :],
)
)
tr0_out = np.vstack(tr0_out)
tr1_out = np.vstack(tr1_out)
np.testing.assert_allclose(
tr0_out, need_result1, rtol=1e-05, atol=1e-05
)
np.testing.assert_allclose(
tr1_out, need_result2, rtol=1e-05, atol=1e-05
)
elif col_type in ["alltoall_single_unequal_split"]:
need_result1 = np.vstack(
(
input1[0 : input1.shape[0] // 2 - 1, :],
input2[0 : input2.shape[0] // 2 - 2, :],
)
)
need_result2 = np.vstack(
(
input1[input1.shape[0] // 2 - 1 :, :],
input2[input2.shape[0] // 2 - 2 :, :],
)
)
tr0_out = np.vstack(tr0_out)
tr1_out = np.vstack(tr1_out)
np.testing.assert_allclose(
tr0_out, need_result1, rtol=1e-05, atol=1e-05
)
np.testing.assert_allclose(
tr1_out, need_result2, rtol=1e-05, atol=1e-05
)
elif col_type == "alltoall_single_unequal_split_empty":
none_shape = list(input1.shape)
none_shape[0] = 0
need_result1 = np.empty(none_shape, dtype=input1.dtype)
need_result2 = input2
tr0_out = np.vstack(tr0_out)
tr1_out = np.vstack(tr1_out)
np.testing.assert_allclose(
tr0_out, need_result1, rtol=1e-05, atol=1e-05
)
np.testing.assert_allclose(
tr1_out, need_result2, rtol=1e-05, atol=1e-05
)
elif col_type == "alltoall_unequal_split":
half_dim0 = input1.shape[0] // 2
half_dim1 = input1.shape[1] // 2
need_result1 = np.concatenate(
[
input1[: half_dim0 - 1, : half_dim1 - 1].flatten(),
input2[half_dim0 - 1 :, : half_dim1 - 2].flatten(),
],
axis=0,
)
need_result2 = np.concatenate(
[
input1[: half_dim0 - 1, half_dim1 - 1 :].flatten(),
input2[half_dim0 - 1 :, half_dim1 - 2 :].flatten(),
],
axis=0,
)
tr0_out = np.concatenate([out.flatten() for out in tr0_out])
tr1_out = np.concatenate([out.flatten() for out in tr1_out])
np.testing.assert_allclose(
tr0_out, need_result1, rtol=1e-05, atol=1e-05
)
np.testing.assert_allclose(
tr1_out, need_result2, rtol=1e-05, atol=1e-05
)
elif col_type == "alltoall_unequal_split_empty":
none_shape = list(input1.shape)
none_shape[0] = 0
need_result1 = input2
need_result2 = np.empty(none_shape, dtype=input1.dtype)
tr0_out = np.vstack(tr0_out)
tr1_out = np.vstack(tr1_out)
np.testing.assert_allclose(
tr0_out, need_result1, rtol=1e-05, atol=1e-05
)
np.testing.assert_allclose(
tr1_out, need_result2, rtol=1e-05, atol=1e-05
)
elif col_type == "sendrecv":
result_data = tr1_out[0]
np.testing.assert_allclose(
input1, result_data, rtol=1e-05, atol=1e-05
)
elif col_type == "global_gather":
in_feat = 2
n_expert = 2
world_size = 2
tot_expert = n_expert * world_size
np.random.seed(pid0)
local_expert_count1 = np.random.randint(
1, 4, size=tot_expert
).astype("int")
expert_ptr1 = np.ones(tot_expert, dtype=np.int32)
expert_ptr1[0] = 0
for i in range(1, tot_expert):
expert_ptr1[i] = expert_ptr1[i - 1] + local_expert_count1[i - 1]
np.random.seed(pid1)
local_expert_count2 = np.random.randint(
1, 4, size=tot_expert
).astype("int")
expert_ptr2 = np.ones(tot_expert, dtype=np.int32)
expert_ptr2[0] = 0
for i in range(1, tot_expert):
expert_ptr2[i] = expert_ptr2[i - 1] + local_expert_count2[i - 1]
global_expert_count1 = np.zeros(tot_expert).astype("int")
global_expert_count2 = np.zeros(tot_expert).astype("int")
global_expert_count1[0:n_expert] = local_expert_count1[0:n_expert]
global_expert_count1[n_expert:] = local_expert_count2[0:n_expert]
global_expert_count2[0:n_expert] = local_expert_count1[n_expert:]
global_expert_count2[n_expert:] = local_expert_count2[n_expert:]
np.random.seed(pid0)
fwd_expert_count = sum(global_expert_count1).astype("int")
local_input_buf1 = np.random.rand(fwd_expert_count, in_feat).astype(
"float32"
)
np.random.seed(pid1)
fwd_expert_count = sum(global_expert_count2).astype("int")
local_input_buf2 = np.random.rand(fwd_expert_count, in_feat).astype(
"float32"
)
output1 = [[], [], [], []]
output2 = [[], [], [], []]
send_ptr1 = 0
send_ptr2 = 0
for i in range(n_expert):
for j in range(world_size):
idx = j * n_expert + i
if j == 0:
output1_part1 = local_input_buf1[
send_ptr1 : send_ptr1 + global_expert_count1[idx], :
]
output1_part2 = local_input_buf2[
send_ptr2 : send_ptr2 + global_expert_count2[idx], :
]
output1[i].extend(output1_part1)
output1[i + n_expert].extend(output1_part2)
else:
output2_part1 = local_input_buf1[
send_ptr1 : send_ptr1 + global_expert_count1[idx]
]
output2_part2 = local_input_buf2[
send_ptr2 : send_ptr2 + global_expert_count2[idx]
]
output2[i].extend(output2_part1)
output2[i + n_expert].extend(output2_part2)
send_ptr1 = send_ptr1 + global_expert_count1[idx]
send_ptr2 = send_ptr2 + global_expert_count2[idx]
result1 = []
result2 = []
def is_empty_list(x):
if isinstance(x, list) and len(x) == 0:
return True
return False
for i in range(tot_expert):
for arr in output1[i]:
if is_empty_list(arr):
continue
result1.append(arr)
for i in range(tot_expert):
for arr in output2[i]:
if is_empty_list(arr):
continue
result2.append(arr)
if result1 == []:
output1 = np.array([])
else:
output1 = np.concatenate(result1, axis=0).reshape(
sum(local_expert_count1), in_feat
)
if result2 == []:
output2 = np.array([])
else:
output2 = np.concatenate(result2, axis=0).reshape(
sum(local_expert_count2), in_feat
)
if tr0_out[0] is None or tr0_out[0].shape[0] == 0:
tr0_out[0] = np.array([])
if tr1_out[0] is None or tr1_out[0].shape[0] == 0:
tr1_out[0] = np.array([])
np.testing.assert_allclose(
tr0_out[0], output1, rtol=1e-05, atol=1e-05
)
np.testing.assert_allclose(
tr1_out[0], output2, rtol=1e-05, atol=1e-05
)
if static_mode == 0:
np.testing.assert_allclose(
tr0_out[1], 2 * local_input_buf1, rtol=1e-05, atol=1e-05
)
np.testing.assert_allclose(
tr1_out[1], 2 * local_input_buf2, rtol=1e-05, atol=1e-05
)
elif col_type == "global_scatter":
np.random.seed(pid0)
local_expert_count1 = np.random.randint(1, 4, size=4).astype("int")
fwd_expert_count = sum(local_expert_count1)
local_input_buf1 = np.random.rand(fwd_expert_count, 2).astype(
"float32"
)
expert_ptr1 = np.ones(4, dtype=np.int32)
expert_ptr1[0] = 0
for i in range(1, 4):
expert_ptr1[i] = expert_ptr1[i - 1] + local_expert_count1[i - 1]
np.random.seed(pid1)
local_expert_count2 = np.random.randint(1, 4, size=4).astype("int")
fwd_expert_count = sum(local_expert_count2)
local_input_buf2 = np.random.rand(fwd_expert_count, 2).astype(
"float32"
)
expert_ptr2 = np.ones(4, dtype=np.int32)
expert_ptr2[0] = 0
for i in range(1, 4):
expert_ptr2[i] = expert_ptr2[i - 1] + local_expert_count2[i - 1]
output1 = []
output2 = []
for i in range(2):
for j in range(2):
idx = j * 2 + i
if j == 0:
# send data to 0 card
output1.append(
local_input_buf1[
expert_ptr1[idx] : expert_ptr1[idx]
+ local_expert_count1[idx]
]
)
output1.append(
local_input_buf2[
expert_ptr2[idx] : expert_ptr2[idx]
+ local_expert_count2[idx]
]
)
else:
output2.append(
local_input_buf1[
expert_ptr1[idx] : expert_ptr1[idx]
+ local_expert_count1[idx]
]
)
output2.append(
local_input_buf2[
expert_ptr2[idx] : expert_ptr2[idx]
+ local_expert_count2[idx]
]
)
if output1 == []:
output1 = np.array([])
else:
output1 = np.concatenate(output1)
if output2 == []:
output2 = np.array([])
else:
output2 = np.concatenate(output2)
if tr0_out[0] is None or tr0_out[0].shape[0] == 0:
tr0_out[0] = np.array([])
if tr1_out[0] is None or tr1_out[0].shape[0] == 0:
tr1_out[0] = np.array([])
np.testing.assert_allclose(
tr0_out[0], output1, rtol=1e-05, atol=1e-05
)
np.testing.assert_allclose(
tr1_out[0], output2, rtol=1e-05, atol=1e-05
)
if static_mode == 0:
np.testing.assert_allclose(
tr0_out[1], 2 * local_input_buf1, rtol=1e-05, atol=1e-05
)
np.testing.assert_allclose(
tr1_out[1], 2 * local_input_buf2, rtol=1e-05, atol=1e-05
)
else:
raise NotImplementedError(
f"col_type {col_type} check_with_place not implemented"
)