chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:40:42 +08:00
commit e25996e7db
15472 changed files with 3536181 additions and 0 deletions
+134
View File
@@ -0,0 +1,134 @@
add_subdirectory(device)
add_subdirectory(profiler)
cc_test(
enforce_test
SRCS enforce_test.cc
DEPS phi common)
cc_test(
place_test
SRCS place_test.cc
DEPS glog phi common)
cc_test(
errors_test
SRCS errors_test.cc
DEPS phi common)
cc_test(
cpu_info_test
SRCS cpu_info_test.cc
DEPS phi common)
cc_test(
os_info_test
SRCS os_info_test.cc
DEPS phi common)
cc_test(
cpu_helper_test
SRCS cpu_helper_test.cc
DEPS phi common)
cc_test(
init_test
SRCS init_test.cc
DEPS phi)
if(WITH_GPU)
nv_test(
device_event_test
SRCS device_event_test.cc
DEPS phi common)
nv_test(
device_context_test
SRCS device_context_test.cu
DEPS phi common)
nv_test(
device_context_test_cuda_graph
SRCS device_context_test_cuda_graph.cu
DEPS phi common)
endif()
if(WITH_ROCM)
hip_test(
device_event_test
SRCS device_event_test.cc
DEPS phi common)
hip_test(
device_context_test
SRCS device_context_test.cu
DEPS phi common)
endif()
cc_test(
timer_test
SRCS timer_test.cc
DEPS phi common)
cc_test(
lodtensor_printer_test
SRCS lodtensor_printer_test.cc
DEPS densetensor_printer)
cc_test(
profiler_test
SRCS profiler_test.cc
DEPS phi common)
cc_test(
float16_test
SRCS float16_test.cc
DEPS lod_tensor)
cc_test(
bfloat16_test
SRCS bfloat16_test.cc
DEPS lod_tensor)
cc_test(
complex_test
SRCS complex_test.cc
DEPS lod_tensor)
if(WITH_GPU)
nv_test(
float16_gpu_test
SRCS float16_test.cu
DEPS lod_tensor)
nv_test(
bfloat16_gpu_test
SRCS bfloat16_test.cu
DEPS lod_tensor)
nv_test(
complex_gpu_test
SRCS complex_test.cu
DEPS lod_tensor)
nv_test(
test_limit_gpu_memory
SRCS test_limit_gpu_memory.cu
DEPS phi common)
endif()
if(WITH_ROCM)
hip_test(
float16_gpu_test
SRCS float16_test.cu
DEPS lod_tensor)
hip_test(
test_limit_gpu_memory
SRCS test_limit_gpu_memory.cu
DEPS phi common)
endif()
if(NOT APPLE AND NOT WIN32)
if(WITH_GPU OR WITH_ROCM)
cc_test(
device_code_test
SRCS device_code_test.cc
DEPS phi common lod_tensor)
endif()
endif()
cc_test(
init_phi_test
SRCS init_phi_test.cc
DEPS phi
common
init_phi
op_dialect
op_dialect_vjp
static_prim_api
primitive_backend_static_experimental)
+165
View File
@@ -0,0 +1,165 @@
/* Copyright (c) 2020 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. */
#include "paddle/phi/common/bfloat16.h"
#include "paddle/phi/kernels/funcs/eigen/extensions.h"
#include "gtest/gtest.h"
#include "paddle/fluid/framework/lod_tensor.h"
#include "paddle/fluid/platform/enforce.h"
namespace paddle::platform {
using bfloat16 = phi::dtype::bfloat16;
using namespace phi::dtype; // NOLINT
TEST(bfloat16, conversion_cpu) {
// Conversion from float
EXPECT_EQ(bfloat16(1.0f).x, 0x3f80);
EXPECT_EQ(bfloat16(0.5f).x, 0x3f00);
EXPECT_EQ(bfloat16(0.33333f).x, 0x3eab);
EXPECT_EQ(bfloat16(0.0f).x, 0x0000);
EXPECT_EQ(bfloat16(-0.0f).x, 0x8000);
EXPECT_EQ(bfloat16(65504.0f).x, 0x4780);
EXPECT_EQ(bfloat16(65536.0f).x, 0x4780);
// Conversion from double
EXPECT_EQ(bfloat16(1.0).x, 0x3f80);
EXPECT_EQ(bfloat16(0.5).x, 0x3f00);
EXPECT_EQ(bfloat16(0.33333).x, 0x3eab);
EXPECT_EQ(bfloat16(0.0).x, 0x0000);
EXPECT_EQ(bfloat16(-0.0).x, 0x8000);
EXPECT_EQ(bfloat16(65504.0).x, 0x4780);
EXPECT_EQ(bfloat16(65536.0).x, 0x4780);
// Conversion from int
EXPECT_EQ(bfloat16(-1).x, 0xbf80);
EXPECT_EQ(bfloat16(0).x, 0x0000);
EXPECT_EQ(bfloat16(1).x, 0x3f80);
EXPECT_EQ(bfloat16(2).x, 0x4000);
EXPECT_EQ(bfloat16(3).x, 0x4040);
// Conversion from bool
EXPECT_EQ(bfloat16(true).x, 0x3f80);
EXPECT_EQ(bfloat16(false).x, 0x0000);
// Assignment operator
bfloat16 v_assign;
v_assign = bfloat16(0.f);
EXPECT_EQ(v_assign.x, 0x0000);
v_assign = 0.5f;
EXPECT_EQ(v_assign.x, 0x3f00);
v_assign = 0.33333;
EXPECT_EQ(v_assign.x, 0x3eab);
v_assign = -1;
EXPECT_EQ(v_assign.x, 0xbf80);
// Conversion operator
EXPECT_EQ(static_cast<float>(bfloat16(0.5f)), 0.5f);
EXPECT_NEAR(static_cast<double>(bfloat16(0.33333)), 0.33333, 0.01);
EXPECT_EQ(static_cast<int>(bfloat16(-1)), -1);
EXPECT_EQ(static_cast<bool>(bfloat16(true)), true);
}
TEST(bfloat16, arithmetic_cpu) {
EXPECT_NEAR(static_cast<float>(bfloat16(1) + bfloat16(1)), 2, 0.001);
EXPECT_EQ(static_cast<float>(bfloat16(5) + bfloat16(-5)), 0);
EXPECT_NEAR(
static_cast<float>(bfloat16(0.33333f) + bfloat16(0.66667f)), 1.0f, 0.01);
EXPECT_EQ(static_cast<float>(bfloat16(3) - bfloat16(5)), -2);
EXPECT_NEAR(static_cast<float>(bfloat16(0.66667f) - bfloat16(0.33333f)),
0.33334f,
0.01);
EXPECT_NEAR(static_cast<float>(bfloat16(3.3f) * bfloat16(2.0f)), 6.6f, 0.01);
EXPECT_NEAR(static_cast<float>(bfloat16(-2.1f) * bfloat16(-3.0f)), 6.3f, 0.1);
EXPECT_NEAR(
static_cast<float>(bfloat16(2.0f) / bfloat16(3.0f)), 0.66667f, 0.01);
EXPECT_EQ(static_cast<float>(bfloat16(1.0f) / bfloat16(2.0f)), 0.5f);
EXPECT_EQ(static_cast<float>(-bfloat16(512.0f)), -512.0f);
EXPECT_EQ(static_cast<float>(-bfloat16(-512.0f)), 512.0f);
}
TEST(bfloat16, comparison_cpu) {
EXPECT_TRUE(bfloat16(1.0f) == bfloat16(1.0f));
EXPECT_FALSE(bfloat16(-1.0f) == bfloat16(-0.5f));
EXPECT_TRUE(bfloat16(1.0f) != bfloat16(0.5f));
EXPECT_FALSE(bfloat16(-1.0f) != bfloat16(-1.0f));
EXPECT_TRUE(bfloat16(1.0f) < bfloat16(2.0f));
EXPECT_FALSE(bfloat16(-1.0f) < bfloat16(-1.0f));
EXPECT_TRUE(bfloat16(1.0f) <= bfloat16(1.0f));
EXPECT_TRUE(bfloat16(2.0f) > bfloat16(1.0f));
EXPECT_FALSE(bfloat16(-2.0f) > bfloat16(-2.0f));
EXPECT_TRUE(bfloat16(2.0f) >= bfloat16(2.0f));
}
TEST(bfloat16, dense_tensor_cpu) {
phi::DenseTensor dense_tensor;
std::vector<bfloat16> input_data = {
bfloat16(1.0f), bfloat16(0.5f), bfloat16(0.33333f), bfloat16(0.0f)};
EXPECT_EQ(input_data[0].x, 0x3f80);
EXPECT_EQ(input_data[1].x, 0x3f00);
EXPECT_EQ(input_data[2].x, 0x3eab);
EXPECT_EQ(input_data[3].x, 0x0000);
dense_tensor.Resize({4, 1});
dense_tensor.set_lod(phi::LegacyLoD({{0, 2, 4}}));
bfloat16* data_ptr = dense_tensor.mutable_data<bfloat16>(CPUPlace());
EXPECT_NE(data_ptr, nullptr);
EXPECT_EQ(input_data.size(), static_cast<size_t>(dense_tensor.numel()));
for (size_t i = 0; i < input_data.size(); ++i) {
data_ptr[i] = input_data[i];
EXPECT_EQ(data_ptr[i].x, input_data[i].x);
}
}
TEST(bfloat16, floating) {
// compile time assert.
PADDLE_ENFORCE_EQ(
std::is_floating_point<bfloat16>::value,
true,
common::errors::Fatal("std::is_floating_point with bfloat16 data type "
"should be equal to true but it is not"));
}
TEST(bfloat16, print) {
bfloat16 a = bfloat16(1.0f);
std::cout << "a:" << a << std::endl;
std::stringstream ss1, ss2;
ss1 << a;
ss2 << 1.0f;
EXPECT_EQ(ss1.str(), ss2.str());
}
// CPU test
TEST(bfloat16, isinf) {
bfloat16 a;
a.x = 0x7f80;
bfloat16 b = bfloat16(INFINITY);
bfloat16 c = static_cast<bfloat16>(INFINITY);
EXPECT_EQ(std::isinf(a), true);
EXPECT_EQ(std::isinf(b), true);
EXPECT_EQ(std::isinf(c), true);
}
TEST(bfloat16, isnan) {
bfloat16 a;
a.x = 0x7fff;
bfloat16 b = bfloat16(NAN);
bfloat16 c = static_cast<bfloat16>(NAN);
EXPECT_EQ(std::isnan(a), true);
EXPECT_EQ(std::isnan(b), true);
EXPECT_EQ(std::isnan(c), true);
}
} // namespace paddle::platform
+132
View File
@@ -0,0 +1,132 @@
/* Copyright (c) 2021 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. */
#include "paddle/phi/common/bfloat16.h"
#include <glog/logging.h>
#include <gtest/gtest.h>
#include <iostream>
#include "paddle/fluid/framework/lod_tensor.h"
#if defined(PADDLE_CUDA_BF16)
namespace paddle {
namespace platform {
using bfloat16 = phi::dtype::bfloat16;
using namespace phi::dtype; // NOLINT
TEST(bfloat16, convert_float32_to_bfloat16_on_gpu) {
// Convert float32 to bfloat16
EXPECT_EQ((bfloat16(1.0f)).x, 0x3f80);
EXPECT_EQ((bfloat16(0.5f)).x, 0x3f00);
EXPECT_EQ((bfloat16(0.33333f)).x, 0x3eab);
EXPECT_EQ((bfloat16(0.0f)).x, 0x0000);
EXPECT_EQ((bfloat16(-0.0f)).x, 0x8000);
EXPECT_EQ((bfloat16(65536.0f)).x, 0x4780);
}
TEST(bfloat16, assignment_operator_on_gpu) {
// Assignment operator
bfloat16 v_assign;
v_assign = bfloat16(1.0f).to_nv_bfloat16();
EXPECT_EQ(v_assign.x, 0x3f80);
v_assign = 0.33333;
EXPECT_EQ(v_assign.x, 0x3eab);
}
TEST(bfloat16, convert_bfloat16_to_float32_on_gpu) {
// Conversion operator
EXPECT_EQ(static_cast<float>(bfloat16(0.5f)), 0.5f);
EXPECT_NEAR(static_cast<double>(bfloat16(0.33333)), 0.33333, 0.01);
EXPECT_EQ(static_cast<int>(bfloat16(-1)), -1);
EXPECT_EQ(static_cast<bool>(bfloat16(true)), true);
}
TEST(bfloat16, dense_tensor_on_gpu) {
phi::DenseTensor src_tensor;
phi::DenseTensor gpu_tensor;
phi::DenseTensor dst_tensor;
bfloat16 *src_ptr =
src_tensor.mutable_data<bfloat16>(common::make_ddim({2, 2}), CPUPlace());
bfloat16 arr[4] = {
bfloat16(1.0f), bfloat16(0.5f), bfloat16(0.33333f), bfloat16(0.0f)};
memcpy(src_ptr, arr, 4 * sizeof(bfloat16));
// CPU DenseTensor to GPU DenseTensor
phi::GPUPlace gpu_place(0);
phi::GPUContext gpu_ctx(gpu_place);
gpu_ctx.SetAllocator(paddle::memory::allocation::AllocatorFacade::Instance()
.GetAllocator(gpu_place, gpu_ctx.stream())
.get());
gpu_ctx.PartialInitWithAllocator();
framework::TensorCopy(src_tensor, gpu_place, gpu_ctx, &gpu_tensor);
// GPU DenseTensor to CPU DenseTensor
framework::TensorCopy(gpu_tensor, CPUPlace(), gpu_ctx, &dst_tensor);
// Sync before comparing DenseTensors
gpu_ctx.Wait();
const bfloat16 *dst_ptr = dst_tensor.data<bfloat16>();
ASSERT_NE(src_ptr, dst_ptr);
for (size_t i = 0; i < 4; ++i) {
EXPECT_EQ(src_ptr[i].x, dst_ptr[i].x);
}
}
TEST(bfloat16, isinf) {
bfloat16 a;
a.x = 0x7f80;
bfloat16 b = bfloat16(INFINITY);
bfloat16 c = static_cast<bfloat16>(INFINITY);
EXPECT_EQ(std::isinf(a), true);
EXPECT_EQ(std::isinf(b), true);
EXPECT_EQ(std::isinf(c), true);
}
TEST(bfloat16, isnan) {
bfloat16 a;
a.x = 0x7fff;
bfloat16 b = bfloat16(NAN);
bfloat16 c = static_cast<bfloat16>(NAN);
EXPECT_EQ(std::isnan(a), true);
EXPECT_EQ(std::isnan(b), true);
EXPECT_EQ(std::isnan(c), true);
}
TEST(bfloat16, cast) {
bfloat16 a;
a.x = 0x0070;
auto b = a;
{
// change semantic, keep the same value
bfloat16 c = reinterpret_cast<bfloat16 &>(reinterpret_cast<unsigned &>(b));
EXPECT_EQ(b, c);
}
{
// use uint32 low 16 bit store float16
uint32_t c = reinterpret_cast<uint32_t &>(b);
bfloat16 d;
d.x = c;
EXPECT_EQ(b, d);
}
}
} // namespace platform
} // namespace paddle
#endif
+326
View File
@@ -0,0 +1,326 @@
// Copyright (c) 2021 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.
#include "paddle/phi/common/complex.h"
#include <complex>
#include "paddle/phi/kernels/funcs/eigen/extensions.h"
#include "gtest/gtest.h"
#include "paddle/fluid/framework/lod_tensor.h"
#include "paddle/fluid/platform/enforce.h"
namespace paddle::platform {
template <typename T>
using complex = phi::dtype::complex<T>;
TEST(complex, conversion_cpu) {
// *********** complex<float> *************
// float to complex<float>
EXPECT_EQ(complex<float>().real, 0.0f);
EXPECT_EQ(complex<float>().imag, 0.0f);
EXPECT_EQ(complex<float>(1.0f, 1.0f).real, 1.0f);
EXPECT_EQ(complex<float>(1.0f, 1.0f).imag, 1.0f);
EXPECT_EQ(complex<float>(0.0f, 1.0f).real, 0.0f);
EXPECT_EQ(complex<float>(0.0f, 1.0f).imag, 1.0f);
EXPECT_EQ(complex<float>(1.0f).real, 1.0f);
EXPECT_EQ(complex<float>(1.0f).imag, 0.0f);
// int to complex<float>
EXPECT_EQ(complex<float>(1).real, 1.0f);
EXPECT_EQ(complex<float>(0).real, 0.0f);
EXPECT_EQ(complex<float>(2).real, 2.0f);
EXPECT_EQ(complex<float>(-2).real, -2.0f);
// bool to complex
EXPECT_EQ(complex<float>(true).real, 1.0f);
EXPECT_EQ(complex<float>(true).imag, 0.0f);
// complex<double> to complex<float>
EXPECT_EQ(complex<float>(complex<double>(1.0, 2.0)).real, 1.0f);
EXPECT_EQ(complex<float>(complex<double>(1.0, 2.0)).imag, 2.0f);
// std::complex<float> to complex<float>
EXPECT_EQ(complex<float>(std::complex<float>(1.0f, 2.0f)).real, 1.0f);
EXPECT_EQ(complex<float>(std::complex<float>(1.0f, 2.0f)).imag, 2.0f);
EXPECT_EQ(complex<float>(std::complex<double>(1.0, 2.0)).real, 1.0f);
EXPECT_EQ(complex<float>(std::complex<double>(1.0, 2.0)).imag, 2.0f);
// Assignment operator
complex<float> c = 1.0f;
EXPECT_EQ(c.real, 1.0f);
EXPECT_EQ(c.imag, 0.0f);
c = complex<float>(2.0, 2.0);
EXPECT_EQ(c.real, 2.0f);
EXPECT_EQ(c.imag, 2.0f);
// Conversion operator
EXPECT_EQ(static_cast<float>(complex<float>(0.5f)), 0.5f);
EXPECT_NEAR(static_cast<double>(complex<float>(0.33333)), 0.33333, 0.01);
EXPECT_EQ(static_cast<int>(complex<float>(-1)), -1);
EXPECT_EQ(static_cast<bool>(complex<float>(true)), true);
// *********** complex<double> *************
// double to complex<double>
EXPECT_EQ(complex<double>().real, 0.0);
EXPECT_EQ(complex<double>().imag, 0.0);
EXPECT_EQ(complex<double>(1.0, 1.0).real, 1.0);
EXPECT_EQ(complex<double>(1.0, 1.0).imag, 1.0);
EXPECT_EQ(complex<double>(0.0, 1.0).real, 0.0);
EXPECT_EQ(complex<double>(0.0, 1.0).imag, 1.0);
EXPECT_EQ(complex<double>(1.0).real, 1.0);
EXPECT_EQ(complex<double>(1.0).imag, 0.0);
// int to complex<double>
EXPECT_EQ(complex<double>(1).real, 1.0);
EXPECT_EQ(complex<double>(0).real, 0.0);
EXPECT_EQ(complex<double>(2).real, 2.0);
EXPECT_EQ(complex<double>(-2).real, -2.0);
// bool to complex
EXPECT_EQ(complex<double>(true).real, 1.0);
EXPECT_EQ(complex<double>(true).imag, 0.0);
// complex<float> to complex<double>
EXPECT_EQ(complex<double>(complex<float>(1.0f, 2.0f)).real, 1.0);
EXPECT_EQ(complex<double>(complex<float>(1.0f, 2.0f)).imag, 2.0);
// std::complex<float> to complex<double>
EXPECT_EQ(complex<double>(std::complex<double>(1.0, 2.0)).real, 1.0);
EXPECT_EQ(complex<double>(std::complex<double>(1.0, 2.0)).imag, 2.0);
EXPECT_EQ(complex<double>(std::complex<double>(1.0, 2.0)).real, 1.0);
EXPECT_EQ(complex<double>(std::complex<double>(1.0, 2.0)).imag, 2.0);
// Assignment operator
complex<double> c1 = 1.0;
EXPECT_EQ(c1.real, 1.0);
EXPECT_EQ(c1.imag, 0.0);
c1 = complex<double>(2.0, 2.0);
EXPECT_EQ(c1.real, 2.0);
EXPECT_EQ(c1.imag, 2.0);
// Conversion operator
EXPECT_EQ(static_cast<double>(complex<double>(0.5)), 0.5);
EXPECT_NEAR(static_cast<double>(complex<double>(0.33333)), 0.33333, 0.01);
EXPECT_EQ(static_cast<int>(complex<double>(-1)), -1);
EXPECT_EQ(static_cast<bool>(complex<double>(true)), true);
}
TEST(bfloat16, comparison_cpu) {
// *********** complex<float> *************
EXPECT_TRUE(complex<float>(1.0f) == complex<float>(1.0f));
EXPECT_TRUE(complex<float>(1.0f, 2.0f) == complex<float>(1.0f, 2.0f));
EXPECT_FALSE(complex<float>(-1.0f) == complex<float>(-0.5f));
EXPECT_TRUE(complex<float>(1.0f) != complex<float>(0.5f));
EXPECT_FALSE(complex<float>(-1.0f) != complex<float>(-1.0f));
EXPECT_TRUE(complex<float>(1.0f) < complex<float>(2.0f));
EXPECT_FALSE(complex<float>(-1.0f) < complex<float>(-1.0f));
EXPECT_TRUE(complex<float>(1.0f) <= complex<float>(1.0f));
EXPECT_TRUE(complex<float>(2.0f) > complex<float>(1.0f));
EXPECT_FALSE(complex<float>(-2.0f) > complex<float>(-2.0f));
EXPECT_TRUE(complex<float>(2.0f) >= complex<float>(2.0f));
// *********** complex<double> *************
EXPECT_TRUE(complex<double>(1.0) == complex<double>(1.0));
EXPECT_TRUE(complex<double>(1.0, 2.0) == complex<double>(1.0, 2.0));
EXPECT_FALSE(complex<double>(-1.0) == complex<double>(-0.5f));
EXPECT_TRUE(complex<double>(1.0) != complex<double>(0.5f));
EXPECT_FALSE(complex<double>(-1.0) != complex<double>(-1.0));
EXPECT_TRUE(complex<double>(1.0) < complex<double>(2.0));
EXPECT_FALSE(complex<double>(-1.0) < complex<double>(-1.0));
EXPECT_TRUE(complex<double>(1.0) <= complex<double>(1.0));
EXPECT_TRUE(complex<double>(2.0) > complex<double>(1.0));
EXPECT_FALSE(complex<double>(-2.0) > complex<double>(-2.0));
EXPECT_TRUE(complex<double>(2.0) >= complex<double>(2.0));
}
TEST(complex, arithmetic_cpu) {
// *********** complex<float> *************
complex<float> a = complex<float>(1, 1) + complex<float>(1, 1);
EXPECT_NEAR(a.real, 2, 0.001);
EXPECT_NEAR(a.imag, 2, 0.001);
complex<float> b = complex<float>(-5, -5) + complex<float>(5, 5);
EXPECT_EQ(b.real, 0);
EXPECT_EQ(b.imag, 0);
complex<float> c =
complex<float>(0.33333f, 0.33333f) + complex<float>(0.66667f, 0.66667f);
EXPECT_NEAR(c.real, 1.0f, 0.01);
EXPECT_NEAR(c.imag, 1.0f, 0.01);
complex<float> d = complex<float>(3) - complex<float>(5);
EXPECT_EQ(d.real, -2);
EXPECT_EQ(d.imag, 0);
complex<float> e =
complex<float>(0.66667f, 0.66667f) - complex<float>(0.33333f, 0.33333f);
EXPECT_NEAR(e.real, 0.33334f, 0.01);
EXPECT_NEAR(e.imag, 0.33334f, 0.01);
complex<float> f = complex<float>(0.33f, 0.33f) * complex<float>(0.2f, 0.2f);
EXPECT_NEAR(f.real, 0.0f, 0.01);
EXPECT_NEAR(f.imag, 0.132f, 0.01);
complex<float> g = complex<float>(0.33f, 0.33f) / complex<float>(0.2f, 0.2f);
EXPECT_NEAR(g.real, 1.65f, 0.01);
EXPECT_NEAR(g.imag, 0.0f, 0.01);
complex<float> h = -complex<float>(0.33f, 0.33f);
EXPECT_NEAR(h.real, -0.33f, 0.01);
EXPECT_NEAR(h.imag, -0.33f, 0.01);
h = -complex<float>(-0.33f, -0.33f);
EXPECT_NEAR(h.real, 0.33f, 0.01);
EXPECT_NEAR(h.imag, 0.33f, 0.01);
complex<float> i = complex<float>(1.0, 1.0);
i += complex<float>(2.0, 2.0);
EXPECT_NEAR(i.real, 3.0f, 0.01);
EXPECT_NEAR(i.imag, 3.0f, 0.01);
i -= complex<float>(1.0, 1.0);
EXPECT_NEAR(i.real, 2.0f, 0.01);
EXPECT_NEAR(i.imag, 2.0f, 0.01);
i *= complex<float>(3, 2);
EXPECT_NEAR(i.real, 2.0f, 0.01);
EXPECT_NEAR(i.imag, 10.0f, 0.01);
i /= complex<float>(3, 2);
EXPECT_NEAR(i.real, 2.0f, 0.01);
EXPECT_NEAR(i.imag, 2.0f, 0.01);
// *********** complex<double> *************
complex<double> a1 = complex<double>(1, 1) + complex<double>(1, 1);
EXPECT_NEAR(a1.real, 2, 0.001);
EXPECT_NEAR(a1.imag, 2, 0.001);
complex<double> b1 = complex<double>(-5, -5) + complex<double>(5, 5);
EXPECT_EQ(b1.real, 0);
EXPECT_EQ(b1.imag, 0);
complex<double> c1 =
complex<double>(0.33333f, 0.33333f) + complex<double>(0.66667f, 0.66667f);
EXPECT_NEAR(c1.real, 1.0f, 0.01);
EXPECT_NEAR(c1.imag, 1.0f, 0.01);
complex<double> d1 = complex<double>(3) - complex<double>(5);
EXPECT_EQ(d1.real, -2);
EXPECT_EQ(d1.imag, 0);
complex<double> e1 =
complex<double>(0.66667f, 0.66667f) - complex<double>(0.33333f, 0.33333f);
EXPECT_NEAR(e1.real, 0.33334f, 0.01);
EXPECT_NEAR(e1.imag, 0.33334f, 0.01);
complex<double> f1 =
complex<double>(0.33f, 0.33f) * complex<double>(0.2f, 0.2f);
EXPECT_NEAR(f1.real, 0.0f, 0.01);
EXPECT_NEAR(f1.imag, 0.132f, 0.01);
complex<double> g1 =
complex<double>(0.33f, 0.33f) / complex<double>(0.2f, 0.2f);
EXPECT_NEAR(g1.real, 1.65f, 0.01);
EXPECT_NEAR(g1.imag, 0.0f, 0.01);
complex<double> h1 = -complex<double>(0.33f, 0.33f);
EXPECT_NEAR(h1.real, -0.33f, 0.01);
EXPECT_NEAR(h1.imag, -0.33f, 0.01);
h1 = -complex<double>(-0.33f, -0.33f);
EXPECT_NEAR(h1.real, 0.33f, 0.01);
EXPECT_NEAR(h1.imag, 0.33f, 0.01);
complex<double> i1 = complex<double>(1.0, 1.0);
i1 += complex<double>(2.0, 2.0);
EXPECT_NEAR(i1.real, 3.0f, 0.01);
EXPECT_NEAR(i1.imag, 3.0f, 0.01);
i1 -= complex<double>(1.0, 1.0);
EXPECT_NEAR(i1.real, 2.0f, 0.01);
EXPECT_NEAR(i1.imag, 2.0f, 0.01);
i1 *= complex<double>(3, 2);
EXPECT_NEAR(i1.real, 2.0f, 0.01);
EXPECT_NEAR(i1.imag, 10.0f, 0.01);
i1 /= complex<double>(3, 2);
EXPECT_NEAR(i1.real, 2.0f, 0.01);
EXPECT_NEAR(i1.imag, 2.0f, 0.01);
}
TEST(complex, print) {
complex<float> a(1.0f);
std::cout << a << std::endl;
complex<double> b(1.0);
std::cout << b << std::endl;
}
TEST(complex, isinf) {
// *********** complex<float> *************
complex<float> a;
a.real = static_cast<float>(INFINITY);
EXPECT_EQ(std::isinf(a), true);
a.imag = static_cast<float>(INFINITY);
EXPECT_EQ(std::isinf(a), true);
complex<float> b = static_cast<float>(INFINITY);
EXPECT_EQ(std::isinf(b), true);
complex<float> c(static_cast<float>(INFINITY), 0);
EXPECT_EQ(std::isinf(c), true);
// *********** complex<double> *************
complex<double> a1;
a1.real = static_cast<double>(INFINITY);
EXPECT_EQ(std::isinf(a1), true);
a1.imag = static_cast<double>(INFINITY);
EXPECT_EQ(std::isinf(a1), true);
complex<double> b1 = static_cast<double>(INFINITY);
EXPECT_EQ(std::isinf(b1), true);
complex<double> c1(static_cast<double>(INFINITY), 0);
EXPECT_EQ(std::isinf(c1), true);
}
TEST(complex, isnan) {
// *********** complex<float> *************
complex<float> a;
a.real = static_cast<float>(NAN);
EXPECT_EQ(std::isnan(a), true);
a.imag = static_cast<float>(NAN);
EXPECT_EQ(std::isnan(a), true);
complex<float> b = static_cast<float>(NAN);
EXPECT_EQ(std::isnan(b), true);
complex<float> c(static_cast<float>(NAN), 0);
EXPECT_EQ(std::isnan(c), true);
// *********** complex<double> *************
complex<double> a1;
a1.real = static_cast<double>(NAN);
EXPECT_EQ(std::isnan(a1), true);
a1.imag = static_cast<double>(NAN);
EXPECT_EQ(std::isnan(a1), true);
complex<double> b1 = static_cast<double>(NAN);
EXPECT_EQ(std::isnan(b1), true);
complex<double> c1(static_cast<double>(NAN), 0);
EXPECT_EQ(std::isnan(c1), true);
}
} // namespace paddle::platform
+364
View File
@@ -0,0 +1,364 @@
// Copyright (c) 2021 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.
#include "paddle/phi/common/complex.h"
#include <glog/logging.h>
#include <gtest/gtest.h>
#include <thrust/complex.h>
#include <bitset>
#include <iostream>
#include "paddle/fluid/framework/lod_tensor.h"
#include "paddle/fluid/framework/tensor_util.h"
#include "paddle/fluid/platform/enforce.h"
#include "paddle/phi/kernels/funcs/eigen/extensions.h"
#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP)
namespace paddle {
namespace platform {
template <typename T>
using complex = phi::dtype::complex<T>;
TEST(complex, conversion_on_gpu) {
// *********** complex<float> *************
// thrust<float> from and to complex<float>
complex<float> a(1.0f, 2.0f);
EXPECT_EQ(complex<float>(thrust::complex<float>(a)).real, 1.0);
EXPECT_EQ(complex<float>(thrust::complex<float>(a)).imag, 2.0);
complex<double> a1(1.0, 2.0);
EXPECT_EQ(complex<double>(thrust::complex<double>(a1)).real, 1.0);
EXPECT_EQ(complex<double>(thrust::complex<double>(a1)).imag, 2.0);
#if defined(PADDLE_WITH_HIP)
EXPECT_EQ(hipFloatComplex(a).real(), 1.0);
EXPECT_EQ(hipFloatComplex(a).imag(), 2.0);
EXPECT_EQ(hipDoubleComplex(a).real(), 1.0);
EXPECT_EQ(hipDoubleComplex(a).imag(), 2.0);
EXPECT_EQ(hipFloatComplex(a1).real(), 1.0);
EXPECT_EQ(hipFloatComplex(a1).imag(), 2.0);
EXPECT_EQ(hipDoubleComplex(a1).real(), 1.0);
EXPECT_EQ(hipDoubleComplex(a1).imag(), 2.0);
#else
EXPECT_EQ(cuCrealf(cuFloatComplex(a)), 1.0);
EXPECT_EQ(cuCimagf(cuFloatComplex(a)), 2.0);
EXPECT_EQ(cuCreal(cuDoubleComplex(a)), 1.0);
EXPECT_EQ(cuCimag(cuDoubleComplex(a)), 2.0);
EXPECT_EQ(cuCrealf(cuFloatComplex(a1)), 1.0);
EXPECT_EQ(cuCimagf(cuFloatComplex(a1)), 2.0);
EXPECT_EQ(cuCreal(cuDoubleComplex(a1)), 1.0);
EXPECT_EQ(cuCimag(cuDoubleComplex(a1)), 2.0);
#endif
EXPECT_EQ(complex<float>().real, 0.0f);
EXPECT_EQ(complex<float>().imag, 0.0f);
EXPECT_EQ(complex<float>(1.0f, 1.0f).real, 1.0f);
EXPECT_EQ(complex<float>(1.0f, 1.0f).imag, 1.0f);
EXPECT_EQ(complex<float>(0.0f, 1.0f).real, 0.0f);
EXPECT_EQ(complex<float>(0.0f, 1.0f).imag, 1.0f);
EXPECT_EQ(complex<float>(1.0f).real, 1.0f);
EXPECT_EQ(complex<float>(1.0f).imag, 0.0f);
// int to complex<float>
EXPECT_EQ(complex<float>(1).real, 1.0f);
EXPECT_EQ(complex<float>(0).real, 0.0f);
EXPECT_EQ(complex<float>(2).real, 2.0f);
EXPECT_EQ(complex<float>(-2).real, -2.0f);
// bool to complex
EXPECT_EQ(complex<float>(true).real, 1.0f);
EXPECT_EQ(complex<float>(true).imag, 0.0f);
// complex<double> to complex<float>
EXPECT_EQ(complex<float>(complex<double>(1.0, 2.0)).real, 1.0f);
EXPECT_EQ(complex<float>(complex<double>(1.0, 2.0)).imag, 2.0f);
// std::complex<float> to complex<float>
EXPECT_EQ(complex<float>(std::complex<float>(1.0f, 2.0f)).real, 1.0f);
EXPECT_EQ(complex<float>(std::complex<float>(1.0f, 2.0f)).imag, 2.0f);
EXPECT_EQ(complex<float>(std::complex<double>(1.0, 2.0)).real, 1.0f);
EXPECT_EQ(complex<float>(std::complex<double>(1.0, 2.0)).imag, 2.0f);
// Assignment operator
complex<float> c = 1.0f;
EXPECT_EQ(c.real, 1.0f);
EXPECT_EQ(c.imag, 0.0f);
c = complex<float>(2.0, 2.0);
EXPECT_EQ(c.real, 2.0f);
EXPECT_EQ(c.imag, 2.0f);
// Conversion operator
EXPECT_EQ(static_cast<float>(complex<float>(0.5f)), 0.5f);
EXPECT_NEAR(static_cast<double>(complex<float>(0.33333)), 0.33333, 0.01);
EXPECT_EQ(static_cast<int>(complex<float>(-1)), -1);
EXPECT_EQ(static_cast<bool>(complex<float>(true)), true);
// *********** complex<double> *************
// double to complex<double>
EXPECT_EQ(complex<double>().real, 0.0);
EXPECT_EQ(complex<double>().imag, 0.0);
EXPECT_EQ(complex<double>(1.0, 1.0).real, 1.0);
EXPECT_EQ(complex<double>(1.0, 1.0).imag, 1.0);
EXPECT_EQ(complex<double>(0.0, 1.0).real, 0.0);
EXPECT_EQ(complex<double>(0.0, 1.0).imag, 1.0);
EXPECT_EQ(complex<double>(1.0).real, 1.0);
EXPECT_EQ(complex<double>(1.0).imag, 0.0);
// int to complex<double>
EXPECT_EQ(complex<double>(1).real, 1.0);
EXPECT_EQ(complex<double>(0).real, 0.0);
EXPECT_EQ(complex<double>(2).real, 2.0);
EXPECT_EQ(complex<double>(-2).real, -2.0);
// bool to complex
EXPECT_EQ(complex<double>(true).real, 1.0);
EXPECT_EQ(complex<double>(true).imag, 0.0);
// complex<float> to complex<double>
EXPECT_EQ(complex<double>(complex<float>(1.0f, 2.0f)).real, 1.0);
EXPECT_EQ(complex<double>(complex<float>(1.0f, 2.0f)).imag, 2.0);
// std::complex<float> to complex<double>
EXPECT_EQ(complex<double>(std::complex<double>(1.0, 2.0)).real, 1.0);
EXPECT_EQ(complex<double>(std::complex<double>(1.0, 2.0)).imag, 2.0);
EXPECT_EQ(complex<double>(std::complex<double>(1.0, 2.0)).real, 1.0);
EXPECT_EQ(complex<double>(std::complex<double>(1.0, 2.0)).imag, 2.0);
// Assignment operator
complex<double> c1 = 1.0;
EXPECT_EQ(c1.real, 1.0);
EXPECT_EQ(c1.imag, 0.0);
c1 = complex<double>(2.0, 2.0);
EXPECT_EQ(c1.real, 2.0);
EXPECT_EQ(c1.imag, 2.0);
// Conversion operator
EXPECT_EQ(static_cast<double>(complex<double>(0.5)), 0.5);
EXPECT_NEAR(static_cast<double>(complex<double>(0.33333)), 0.33333, 0.01);
EXPECT_EQ(static_cast<int>(complex<double>(-1)), -1);
EXPECT_EQ(static_cast<bool>(complex<double>(true)), true);
}
TEST(bfloat16, comparison_cpu) {
// *********** complex<float> *************
EXPECT_TRUE(complex<float>(1.0f) == complex<float>(1.0f));
EXPECT_TRUE(complex<float>(1.0f, 2.0f) == complex<float>(1.0f, 2.0f));
EXPECT_FALSE(complex<float>(-1.0f) == complex<float>(-0.5f));
EXPECT_TRUE(complex<float>(1.0f) != complex<float>(0.5f));
EXPECT_FALSE(complex<float>(-1.0f) != complex<float>(-1.0f));
EXPECT_TRUE(complex<float>(1.0f) < complex<float>(2.0f));
EXPECT_FALSE(complex<float>(-1.0f) < complex<float>(-1.0f));
EXPECT_TRUE(complex<float>(1.0f) <= complex<float>(1.0f));
EXPECT_TRUE(complex<float>(2.0f) > complex<float>(1.0f));
EXPECT_FALSE(complex<float>(-2.0f) > complex<float>(-2.0f));
EXPECT_TRUE(complex<float>(2.0f) >= complex<float>(2.0f));
// *********** complex<double> *************
EXPECT_TRUE(complex<double>(1.0) == complex<double>(1.0));
EXPECT_TRUE(complex<double>(1.0, 2.0) == complex<double>(1.0, 2.0));
EXPECT_FALSE(complex<double>(-1.0) == complex<double>(-0.5f));
EXPECT_TRUE(complex<double>(1.0) != complex<double>(0.5f));
EXPECT_FALSE(complex<double>(-1.0) != complex<double>(-1.0));
EXPECT_TRUE(complex<double>(1.0) < complex<double>(2.0));
EXPECT_FALSE(complex<double>(-1.0) < complex<double>(-1.0));
EXPECT_TRUE(complex<double>(1.0) <= complex<double>(1.0));
EXPECT_TRUE(complex<double>(2.0) > complex<double>(1.0));
EXPECT_FALSE(complex<double>(-2.0) > complex<double>(-2.0));
EXPECT_TRUE(complex<double>(2.0) >= complex<double>(2.0));
}
TEST(complex, arithmetic_cpu) {
// *********** complex<float> *************
complex<float> a = complex<float>(1, 1) + complex<float>(1, 1);
EXPECT_NEAR(a.real, 2, 0.001);
EXPECT_NEAR(a.imag, 2, 0.001);
complex<float> b = complex<float>(-5, -5) + complex<float>(5, 5);
EXPECT_EQ(b.real, 0);
EXPECT_EQ(b.imag, 0);
complex<float> c =
complex<float>(0.33333f, 0.33333f) + complex<float>(0.66667f, 0.66667f);
EXPECT_NEAR(c.real, 1.0f, 0.01);
EXPECT_NEAR(c.imag, 1.0f, 0.01);
complex<float> d = complex<float>(3) - complex<float>(5);
EXPECT_EQ(d.real, -2);
EXPECT_EQ(d.imag, 0);
complex<float> e =
complex<float>(0.66667f, 0.66667f) - complex<float>(0.33333f, 0.33333f);
EXPECT_NEAR(e.real, 0.33334f, 0.01);
EXPECT_NEAR(e.imag, 0.33334f, 0.01);
complex<float> f = complex<float>(0.33f, 0.33f) * complex<float>(0.2f, 0.2f);
EXPECT_NEAR(f.real, 0.0f, 0.01);
EXPECT_NEAR(f.imag, 0.132f, 0.01);
complex<float> g = complex<float>(0.33f, 0.33f) / complex<float>(0.2f, 0.2f);
EXPECT_NEAR(g.real, 1.65f, 0.01);
EXPECT_NEAR(g.imag, 0.0f, 0.01);
complex<float> h = -complex<float>(0.33f, 0.33f);
EXPECT_NEAR(h.real, -0.33f, 0.01);
EXPECT_NEAR(h.imag, -0.33f, 0.01);
h = -complex<float>(-0.33f, -0.33f);
EXPECT_NEAR(h.real, 0.33f, 0.01);
EXPECT_NEAR(h.imag, 0.33f, 0.01);
complex<float> i = complex<float>(1.0, 1.0);
i += complex<float>(2.0, 2.0);
EXPECT_NEAR(i.real, 3.0f, 0.01);
EXPECT_NEAR(i.imag, 3.0f, 0.01);
i -= complex<float>(1.0, 1.0);
EXPECT_NEAR(i.real, 2.0f, 0.01);
EXPECT_NEAR(i.imag, 2.0f, 0.01);
i *= complex<float>(3, 2);
EXPECT_NEAR(i.real, 2.0f, 0.01);
EXPECT_NEAR(i.imag, 10.0f, 0.01);
i /= complex<float>(3, 2);
EXPECT_NEAR(i.real, 2.0f, 0.01);
EXPECT_NEAR(i.imag, 2.0f, 0.01);
// *********** complex<double> *************
complex<double> a1 = complex<double>(1, 1) + complex<double>(1, 1);
EXPECT_NEAR(a1.real, 2, 0.001);
EXPECT_NEAR(a1.imag, 2, 0.001);
complex<double> b1 = complex<double>(-5, -5) + complex<double>(5, 5);
EXPECT_EQ(b1.real, 0);
EXPECT_EQ(b1.imag, 0);
complex<double> c1 =
complex<double>(0.33333f, 0.33333f) + complex<double>(0.66667f, 0.66667f);
EXPECT_NEAR(c1.real, 1.0f, 0.01);
EXPECT_NEAR(c1.imag, 1.0f, 0.01);
complex<double> d1 = complex<double>(3) - complex<double>(5);
EXPECT_EQ(d1.real, -2);
EXPECT_EQ(d1.imag, 0);
complex<double> e1 =
complex<double>(0.66667f, 0.66667f) - complex<double>(0.33333f, 0.33333f);
EXPECT_NEAR(e1.real, 0.33334f, 0.01);
EXPECT_NEAR(e1.imag, 0.33334f, 0.01);
complex<double> f1 =
complex<double>(0.33f, 0.33f) * complex<double>(0.2f, 0.2f);
EXPECT_NEAR(f1.real, 0.0f, 0.01);
EXPECT_NEAR(f1.imag, 0.132f, 0.01);
complex<double> g1 =
complex<double>(0.33f, 0.33f) / complex<double>(0.2f, 0.2f);
EXPECT_NEAR(g1.real, 1.65f, 0.01);
EXPECT_NEAR(g1.imag, 0.0f, 0.01);
complex<double> h1 = -complex<double>(0.33f, 0.33f);
EXPECT_NEAR(h1.real, -0.33f, 0.01);
EXPECT_NEAR(h1.imag, -0.33f, 0.01);
h1 = -complex<double>(-0.33f, -0.33f);
EXPECT_NEAR(h1.real, 0.33f, 0.01);
EXPECT_NEAR(h1.imag, 0.33f, 0.01);
complex<double> i1 = complex<double>(1.0, 1.0);
i1 += complex<double>(2.0, 2.0);
EXPECT_NEAR(i1.real, 3.0f, 0.01);
EXPECT_NEAR(i1.imag, 3.0f, 0.01);
i1 -= complex<double>(1.0, 1.0);
EXPECT_NEAR(i1.real, 2.0f, 0.01);
EXPECT_NEAR(i1.imag, 2.0f, 0.01);
i1 *= complex<double>(3, 2);
EXPECT_NEAR(i1.real, 2.0f, 0.01);
EXPECT_NEAR(i1.imag, 10.0f, 0.01);
i1 /= complex<double>(3, 2);
EXPECT_NEAR(i1.real, 2.0f, 0.01);
EXPECT_NEAR(i1.imag, 2.0f, 0.01);
}
TEST(complex, print) {
complex<float> a(1.0f);
std::cout << a << std::endl;
complex<double> b(1.0);
std::cout << b << std::endl;
}
TEST(complex, isinf) {
// *********** complex<float> *************
complex<float> a;
a.real = static_cast<float>(INFINITY);
EXPECT_EQ(std::isinf(a), true);
a.imag = static_cast<float>(INFINITY);
EXPECT_EQ(std::isinf(a), true);
complex<float> b = static_cast<float>(INFINITY);
EXPECT_EQ(std::isinf(b), true);
complex<float> c(static_cast<float>(INFINITY), 0);
EXPECT_EQ(std::isinf(c), true);
// *********** complex<double> *************
complex<double> a1;
a1.real = static_cast<double>(INFINITY);
EXPECT_EQ(std::isinf(a1), true);
a1.imag = static_cast<double>(INFINITY);
EXPECT_EQ(std::isinf(a1), true);
complex<double> b1 = static_cast<double>(INFINITY);
EXPECT_EQ(std::isinf(b1), true);
complex<double> c1(static_cast<double>(INFINITY), 0);
EXPECT_EQ(std::isinf(c1), true);
}
TEST(complex, isnan) {
// *********** complex<float> *************
complex<float> a;
a.real = static_cast<float>(NAN);
EXPECT_EQ(std::isnan(a), true);
a.imag = static_cast<float>(NAN);
EXPECT_EQ(std::isnan(a), true);
complex<float> b = static_cast<float>(NAN);
EXPECT_EQ(std::isnan(b), true);
complex<float> c(static_cast<float>(NAN), 0);
EXPECT_EQ(std::isnan(c), true);
// *********** complex<double> *************
complex<double> a1;
a1.real = static_cast<double>(NAN);
EXPECT_EQ(std::isnan(a1), true);
a1.imag = static_cast<double>(NAN);
EXPECT_EQ(std::isnan(a1), true);
complex<double> b1 = static_cast<double>(NAN);
EXPECT_EQ(std::isnan(b1), true);
complex<double> c1(static_cast<double>(NAN), 0);
EXPECT_EQ(std::isnan(c1), true);
}
} // namespace platform
} // namespace paddle
#endif
@@ -0,0 +1,22 @@
/* Copyright (c) 2018 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. */
#include "paddle/phi/core/platform/cpu_helper.h"
#include "gtest/gtest.h"
TEST(CpuHelper, SetNumThread) {
paddle::platform::SetNumThreads(1);
paddle::platform::SetNumThreads(4);
}
+34
View File
@@ -0,0 +1,34 @@
// Copyright (c) 2018 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.
#include "paddle/phi/backends/cpu/cpu_info.h"
#include <sstream>
#include "gtest/gtest.h"
#include "paddle/common/flags.h"
#include "paddle/utils/string/printf.h"
COMMON_DECLARE_double(fraction_of_cpu_memory_to_use);
TEST(CpuMemoryUsage, Print) {
std::stringstream ss;
size_t memory_size =
phi::backends::cpu::CpuMaxAllocSize() / 1024 / 1024 / 1024;
float use_percent = FLAGS_fraction_of_cpu_memory_to_use * 100; // NOLINT
std::cout << paddle::string::Sprintf("\n%.2f %% of CPU Memory Usage: %d GB\n",
use_percent,
memory_size)
<< std::endl;
}
@@ -0,0 +1,2 @@
add_subdirectory(custom)
add_subdirectory(gpu)
@@ -0,0 +1,3 @@
if(WITH_CUSTOM_DEVICE)
paddle_test(custom_device_test SRCS custom_device_test.cc)
endif()
@@ -0,0 +1,267 @@
// Copyright (c) 2022 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.
#include <gtest/gtest.h>
#include <array>
#include <string>
#include "paddle/fluid/framework/tensor_util.h"
#include "paddle/fluid/platform/init.h"
#include "paddle/phi/backends/custom/fake_cpu_device.h"
#include "paddle/phi/backends/device_manager.h"
#include "paddle/phi/common/memory_utils.h"
#include "paddle/phi/core/memory/allocation/allocator_facade.h"
#include "paddle/phi/core/platform/device_context.h"
void RegisterDevice() {
CustomRuntimeParams runtime_params;
runtime_params.size = sizeof(CustomRuntimeParams);
auto device_interface = std::make_unique<C_DeviceInterface>();
runtime_params.interface = device_interface.get();
std::memset(runtime_params.interface, 0, sizeof(C_DeviceInterface));
runtime_params.interface->size = sizeof(C_DeviceInterface);
InitFakeCPUDevice(&runtime_params);
phi::LoadCustomRuntimeLib(
runtime_params, std::move(device_interface), "", nullptr);
std::vector<std::string> passes =
phi::CustomDevicePassManager::Instance()->GetCustomDevicePass();
EXPECT_EQ(passes[0], "fake_cpu_device_pass");
}
void InitDevice() {
RegisterDevice();
EXPECT_GT(static_cast<int>(phi::DeviceManager::GetAllDeviceTypes().size()),
0);
auto place = phi::CustomPlace(DEVICE_TYPE, 0);
auto device = phi::DeviceManager::GetDeviceWithPlace(place);
EXPECT_NE(device, nullptr);
std::vector<phi::Place> places;
auto device_types = phi::DeviceManager::GetAllDeviceTypes();
for (auto dev_type : device_types) {
auto devices = phi::DeviceManager::GetDeviceList(dev_type);
for (auto dev_id : devices) {
places.push_back(phi::PlaceHelper::CreatePlace(dev_type, dev_id));
}
}
EXPECT_GT(static_cast<int>(places.size()), 0);
phi::DeviceContextPool::Init(places);
}
void TestDeviceInterface(const phi::Place& place) {
std::cout << "TestDeviceInterface on " << place << std::endl;
if (phi::is_custom_place(place)) {
auto device = phi::DeviceManager::GetDeviceWithPlace(place);
auto dev_type = phi::PlaceHelper::GetDeviceType(place);
auto p1 =
device->MemoryAllocate(phi::DeviceManager::GetMinChunkSize(place));
EXPECT_NE(p1, nullptr);
phi::DeviceManager::SetDevice(place);
auto dev_id = phi::DeviceManager::GetDevice(dev_type);
EXPECT_EQ(dev_id, place.GetDeviceId());
}
}
void TestTensorMutableData(const phi::Place& place) {
std::cout << "TestTensorInitialization on " << place << std::endl;
phi::DenseTensor src_tensor;
float* p1 = nullptr;
float* p2 = nullptr;
// initialization
p1 = src_tensor.mutable_data<float>(common::make_ddim({1, 2, 3}), place);
auto p1_holder = src_tensor.Holder();
EXPECT_NE(p1, nullptr);
// set src_tensor a new dim with large size
// memory is supposed to be re-allocated
p2 = src_tensor.mutable_data<float>(common::make_ddim({3, 1024}), place);
auto p2_holder = src_tensor.Holder();
EXPECT_NE(p2, nullptr);
EXPECT_NE(p1_holder.get(), p2_holder.get());
// set src_tensor a new dim with same size
// memory block is supposed to be unchanged
p1 = src_tensor.mutable_data<float>(common::make_ddim({2, 2, 3}), place);
EXPECT_EQ(p1, p2);
// set src_tensor a new dim with smaller size
// memory block is supposed to be unchanged
p2 = src_tensor.mutable_data<float>(common::make_ddim({2, 2}), place);
EXPECT_EQ(p1, p2);
}
void TestTensorShareDataWith(const phi::Place& place) {
std::cout << "TestTensorShareDataWith on " << place << std::endl;
phi::DenseTensor src_tensor;
phi::DenseTensor dst_tensor;
src_tensor.mutable_data<int>(common::make_ddim({2, 3, 4}), place);
dst_tensor.ShareDataWith(src_tensor);
ASSERT_EQ(src_tensor.data<int>(), dst_tensor.data<int>());
}
void TestTensorUtils(const phi::Place& place) {
std::cout << "TestTensorUtils on " << place << std::endl;
if (phi::is_custom_place(place) == false) {
return;
}
phi::DenseTensor src_tensor;
phi::DenseTensor gpu_tensor;
phi::DenseTensor dst_tensor;
int* src_ptr =
src_tensor.mutable_data<int>(common::make_ddim({3, 3}), phi::CPUPlace());
std::array<int, 9> arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};
memcpy(src_ptr, arr.data(), 9 * sizeof(int));
// CPU Tensor to GPU Tensor
phi::CustomContext gpu_ctx(place);
paddle::framework::TensorCopy(src_tensor, place, gpu_ctx, &gpu_tensor);
#if 0
// GPU Tensor to CPU Tensor
auto cpu_place = new phi::CPUPlace();
paddle::framework::TensorCopy(gpu_tensor, *cpu_place, gpu_ctx, &dst_tensor);
// Sync before Compare Tensors
gpu_ctx.Wait();
const int* dst_ptr = dst_tensor.data<int>();
EXPECT_NE(src_ptr, dst_ptr);
for (size_t i = 0; i < 9; ++i) {
EXPECT_EQ(src_ptr[i], dst_ptr[i]);
}
// Copy the same tensor
paddle::framework::TensorCopy(gpu_tensor, place, gpu_ctx, &gpu_tensor);
gpu_ctx.Wait();
const int* dst_ptr_tmp = dst_tensor.data<int>();
EXPECT_NE(src_ptr, dst_ptr_tmp);
for (size_t i = 0; i < 9; ++i) {
EXPECT_EQ(src_ptr[i], dst_ptr_tmp[i]);
}
phi::DenseTensor slice_tensor = src_tensor.Slice(1, 2);
// CPU Slice Tensor to GPU Tensor
paddle::framework::TensorCopy(slice_tensor, place, gpu_ctx, &gpu_tensor);
// GPU Tensor to CPU Tensor
paddle::framework::TensorCopy(gpu_tensor, *cpu_place, gpu_ctx, &dst_tensor);
// Sync before Compare Slice Tensors
gpu_ctx.Wait();
const int* slice_ptr = slice_tensor.data<int>();
dst_ptr = dst_tensor.data<int>();
EXPECT_NE(dst_ptr, slice_ptr);
for (size_t i = 0; i < 3; ++i) {
EXPECT_EQ(dst_ptr[i], slice_ptr[i]);
}
EXPECT_TRUE(dst_tensor.layout() == src_tensor.layout());
#endif
}
void TestCustomCCL(const phi::Place& place) {
std::cout << "TestCustomCCL on " << place << std::endl;
if (phi::is_custom_place(place) == false) {
return;
}
std::string dev_type = place.GetDeviceType();
phi::ccl::CCLComm comm;
phi::stream::Stream stream(place, nullptr);
phi::ccl::CCLRootId root_id;
phi::DeviceManager::CCLDestroyComm(dev_type, nullptr);
phi::DeviceManager::CCLGetUniqueId(dev_type, &root_id);
phi::DeviceManager::CCLCommInitRank(dev_type, 0, &root_id, 0, nullptr);
phi::DeviceManager::CCLBroadcast(dev_type,
nullptr,
0,
phi::DataType::FLOAT32,
0,
comm,
stream.raw_stream());
phi::DeviceManager::CCLAllReduce(dev_type,
nullptr,
nullptr,
0,
phi::DataType::FLOAT32,
phi::ccl::CCLReduceOp::SUM,
comm,
stream.raw_stream());
phi::DeviceManager::CCLReduce(dev_type,
nullptr,
nullptr,
0,
phi::DataType::FLOAT32,
phi::ccl::CCLReduceOp::SUM,
0,
comm,
stream.raw_stream());
phi::DeviceManager::CCLAllGather(dev_type,
nullptr,
nullptr,
0,
phi::DataType::FLOAT32,
comm,
stream.raw_stream());
phi::DeviceManager::CCLReduceScatter(dev_type,
nullptr,
nullptr,
0,
phi::DataType::FLOAT32,
phi::ccl::CCLReduceOp::SUM,
comm,
stream.raw_stream());
phi::DeviceManager::CCLGroupStart(dev_type);
phi::DeviceManager::CCLGroupEnd(dev_type);
phi::DeviceManager::CCLSend(dev_type,
nullptr,
0,
phi::DataType::FLOAT32,
0,
comm,
stream.raw_stream());
phi::DeviceManager::CCLRecv(dev_type,
nullptr,
0,
phi::DataType::FLOAT32,
0,
comm,
stream.raw_stream());
}
TEST(CustomDevice, Tensor) {
paddle::framework::InitMemoryMethod();
InitDevice();
auto dev_types = phi::DeviceManager::GetAllDeviceTypes();
for (const auto& dev_type : dev_types) {
std::cout << "Test on " << dev_type << std::endl;
EXPECT_GT(static_cast<int>(phi::DeviceManager::GetDeviceCount(dev_type)),
0);
auto place = phi::PlaceHelper::CreatePlace(dev_type);
TestDeviceInterface(place);
TestTensorMutableData(place);
TestTensorShareDataWith(place);
TestTensorUtils(place);
TestCustomCCL(place);
}
}
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
@@ -0,0 +1,17 @@
if(WITH_GPU)
add_subdirectory(cuda)
nv_test(cuda_helper_test SRCS cuda_helper_test.cu)
nv_test(
cudnn_desc_test
SRCS cudnn_desc_test.cc
DEPS phi common)
elseif(WITH_ROCM)
add_subdirectory(rocm)
hip_test(cuda_helper_test SRCS cuda_helper_test.cu)
hip_test(
cudnn_desc_test
SRCS cudnn_desc_test.cc
DEPS phi common)
endif()
@@ -0,0 +1,4 @@
nv_test(
cudnn_helper_test
SRCS cudnn_helper_test.cc
DEPS phi common)
@@ -0,0 +1,163 @@
/* Copyright (c) 2016 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. */
#define GOOGLE_GLOG_DLL_DECL
#include <gtest/gtest.h>
#include "paddle/phi/core/platform/device/gpu/gpu_dnn.h"
TEST(CudnnHelper, ScopedTensorDescriptor) {
using phi::DataLayout;
using phi::backends::gpu::ScopedTensorDescriptor;
ScopedTensorDescriptor tensor_desc;
std::vector<int> shape = {2, 4, 6, 6};
auto desc = tensor_desc.descriptor<float>(DataLayout::NCHW, shape);
cudnnDataType_t type;
int nd;
std::vector<int> dims(4);
std::vector<int> strides(4);
phi::dynload::cudnnGetTensorNdDescriptor(
desc, 4, &type, &nd, dims.data(), strides.data());
EXPECT_EQ(nd, 4);
for (size_t i = 0; i < dims.size(); ++i) {
EXPECT_EQ(dims[i], shape[i]);
}
EXPECT_EQ(strides[3], 1);
EXPECT_EQ(strides[2], 6);
EXPECT_EQ(strides[1], 36);
EXPECT_EQ(strides[0], 144);
// test tensor5d: ScopedTensorDescriptor
ScopedTensorDescriptor tensor5d_desc;
std::vector<int> shape_5d = {2, 4, 6, 6, 6};
auto desc_5d = tensor5d_desc.descriptor<float>(DataLayout::NCDHW, shape_5d);
std::vector<int> dims_5d(5);
std::vector<int> strides_5d(5);
phi::dynload::cudnnGetTensorNdDescriptor(
desc_5d, 5, &type, &nd, dims_5d.data(), strides_5d.data());
EXPECT_EQ(nd, 5);
for (size_t i = 0; i < dims_5d.size(); ++i) {
EXPECT_EQ(dims_5d[i], shape_5d[i]);
}
EXPECT_EQ(strides_5d[4], 1);
EXPECT_EQ(strides_5d[3], 6);
EXPECT_EQ(strides_5d[2], 36);
EXPECT_EQ(strides_5d[1], 216);
EXPECT_EQ(strides_5d[0], 864);
}
TEST(CudnnHelper, ScopedFilterDescriptor) {
using phi::DataLayout;
using phi::backends::gpu::GetCudnnTensorFormat;
using phi::backends::gpu::ScopedFilterDescriptor;
ScopedFilterDescriptor filter_desc;
std::vector<int> shape = {2, 3, 3};
auto desc = filter_desc.descriptor<float>(DataLayout::NCHW, shape);
cudnnDataType_t type;
int nd;
cudnnTensorFormat_t format;
std::vector<int> kernel(3);
phi::dynload::cudnnGetFilterNdDescriptor(
desc, 3, &type, &format, &nd, kernel.data());
EXPECT_EQ(GetCudnnTensorFormat(DataLayout::NCHW), format);
EXPECT_EQ(nd, 3);
for (size_t i = 0; i < shape.size(); ++i) {
EXPECT_EQ(kernel[i], shape[i]);
}
ScopedFilterDescriptor filter_desc_4d;
std::vector<int> shape_4d = {2, 3, 3, 3};
auto desc_4d = filter_desc.descriptor<float>(DataLayout::NCDHW, shape_4d);
std::vector<int> kernel_4d(4);
phi::dynload::cudnnGetFilterNdDescriptor(
desc_4d, 4, &type, &format, &nd, kernel_4d.data());
EXPECT_EQ(GetCudnnTensorFormat(DataLayout::NCHW), format);
EXPECT_EQ(nd, 4);
for (size_t i = 0; i < shape_4d.size(); ++i) {
EXPECT_EQ(kernel_4d[i], shape_4d[i]);
}
}
TEST(CudnnHelper, ScopedConvolutionDescriptor) {
using phi::backends::gpu::ScopedConvolutionDescriptor;
ScopedConvolutionDescriptor conv_desc;
std::vector<int> src_pads = {2, 2, 2};
std::vector<int> src_strides = {1, 1, 1};
std::vector<int> src_dilations = {1, 1, 1};
auto desc = conv_desc.descriptor<float>(src_pads, src_strides, src_dilations);
cudnnDataType_t type;
cudnnConvolutionMode_t mode;
int nd;
std::vector<int> pads(3);
std::vector<int> strides(3);
std::vector<int> dilations(3);
phi::dynload::cudnnGetConvolutionNdDescriptor(desc,
3,
&nd,
pads.data(),
strides.data(),
dilations.data(),
&mode,
&type);
EXPECT_EQ(nd, 3);
for (size_t i = 0; i < src_pads.size(); ++i) {
EXPECT_EQ(pads[i], src_pads[i]);
EXPECT_EQ(strides[i], src_strides[i]);
EXPECT_EQ(dilations[i], src_dilations[i]);
}
EXPECT_EQ(mode, CUDNN_CROSS_CORRELATION);
}
TEST(CudnnHelper, ScopedPoolingDescriptor) {
using phi::backends::gpu::PoolingMode;
using phi::backends::gpu::ScopedPoolingDescriptor;
ScopedPoolingDescriptor pool_desc;
std::vector<int> src_kernel = {2, 2, 5};
std::vector<int> src_pads = {1, 1, 2};
std::vector<int> src_strides = {2, 2, 3};
auto desc = pool_desc.descriptor(
PoolingMode::kMaximum, src_kernel, src_pads, src_strides);
cudnnPoolingMode_t mode;
cudnnNanPropagation_t nan_t = CUDNN_PROPAGATE_NAN;
int nd;
std::vector<int> kernel(3);
std::vector<int> pads(3);
std::vector<int> strides(3);
phi::dynload::cudnnGetPoolingNdDescriptor(
desc, 3, &mode, &nan_t, &nd, kernel.data(), pads.data(), strides.data());
EXPECT_EQ(nd, 3);
for (size_t i = 0; i < src_pads.size(); ++i) {
EXPECT_EQ(kernel[i], src_kernel[i]);
EXPECT_EQ(pads[i], src_pads[i]);
EXPECT_EQ(strides[i], src_strides[i]);
}
EXPECT_EQ(mode, CUDNN_POOLING_MAX);
}
@@ -0,0 +1,310 @@
// Copyright (c) 2018 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.
#include <gtest/gtest.h>
#include <algorithm>
#include <iostream>
#ifdef _WIN32
#include <numeric>
#endif
#include <random>
#include "paddle/phi/backends/gpu/gpu_device_function.h"
#include "paddle/phi/backends/gpu/gpu_primitives.h"
#include "paddle/phi/common/float16.h"
#include "paddle/phi/core/platform/device/gpu/gpu_helper.h"
using phi::PADDLE_CUDA_NUM_THREADS;
using phi::dtype::float16;
template <typename T>
__global__ void AddKernel(const T* data_a, T* data_b, size_t num) {
CUDA_KERNEL_LOOP(i, num) { phi::CudaAtomicAdd(&data_b[i], data_a[i]); }
}
template <typename T>
struct AddFunctor {
T operator()(const T& a, const T& b) { return a + b; }
};
template <typename T>
void TestCase(size_t num) {
T *in1, *in2, *out;
T *d_in1, *d_in2;
size_t size = sizeof(T) * num;
#ifdef PADDLE_WITH_HIP
hipMalloc(reinterpret_cast<void**>(&d_in1), size);
hipMalloc(reinterpret_cast<void**>(&d_in2), size);
#else
cudaMalloc(reinterpret_cast<void**>(&d_in1), size);
cudaMalloc(reinterpret_cast<void**>(&d_in2), size);
#endif
in1 = reinterpret_cast<T*>(malloc(size));
in2 = reinterpret_cast<T*>(malloc(size));
out = reinterpret_cast<T*>(malloc(size));
std::minstd_rand engine;
std::uniform_real_distribution<double> dist(0.0, 1.0);
for (size_t i = 0; i < num; ++i) {
in1[i] = static_cast<T>(dist(engine));
in2[i] = static_cast<T>(dist(engine));
}
#ifdef PADDLE_WITH_HIP
hipMemcpy(d_in1, in1, size, hipMemcpyHostToDevice);
hipMemcpy(d_in2, in2, size, hipMemcpyHostToDevice);
hipLaunchKernelGGL(HIP_KERNEL_NAME(AddKernel<T>),
dim3(1),
dim3(PADDLE_CUDA_NUM_THREADS),
0,
0,
d_in1,
d_in2,
num);
hipDeviceSynchronize();
hipMemcpy(out, d_in2, size, hipMemcpyDeviceToHost);
hipDeviceSynchronize();
#else
cudaMemcpy(d_in1, in1, size, cudaMemcpyHostToDevice);
cudaMemcpy(d_in2, in2, size, cudaMemcpyHostToDevice);
AddKernel<T><<<1, PADDLE_CUDA_NUM_THREADS>>>(d_in1, d_in2, num);
cudaDeviceSynchronize();
cudaMemcpy(out, d_in2, size, cudaMemcpyDeviceToHost);
cudaDeviceSynchronize();
#endif
for (size_t i = 0; i < num; ++i) {
// NOTE(dzhwinter): the float16 add has small underflow/overflow
// so we use EXPECT_NEAR to check the result.
EXPECT_NEAR(static_cast<float>(out[i]),
static_cast<float>(AddFunctor<T>()(in1[i], in2[i])),
0.001);
}
free(in1);
free(in2);
free(out);
#ifdef PADDLE_WITH_HIP
hipFree(d_in1);
hipFree(d_in2);
#else
cudaFree(d_in1);
cudaFree(d_in2);
#endif
}
// cuda primitives
TEST(CudaAtomic, Add) {
TestCase<float>(static_cast<size_t>(10));
TestCase<float>(static_cast<size_t>(1024 * 1024));
TestCase<double>(static_cast<size_t>(10));
TestCase<double>(static_cast<size_t>(1024 * 1024));
}
TEST(CudaAtomic, float16) {
TestCase<float16>(static_cast<size_t>(1));
TestCase<float16>(static_cast<size_t>(2));
TestCase<float16>(static_cast<size_t>(3));
TestCase<float16>(static_cast<size_t>(10));
TestCase<float16>(static_cast<size_t>(1024 * 1024));
}
// unalignment of uint8
void TestUnalign(size_t num, const int shift_bit) {
ASSERT_EQ(num % 2, 0);
float16 *in1, *in2, *out;
float16 *d_in1, *d_in2;
size_t size = sizeof(uint8_t) * (num + shift_bit);
size_t array_size = sizeof(float16) * (num / 2);
#ifdef PADDLE_WITH_HIP
hipMalloc(reinterpret_cast<void**>(&d_in1), size);
hipMalloc(reinterpret_cast<void**>(&d_in2), size);
#else
cudaMalloc(reinterpret_cast<void**>(&d_in1), size);
cudaMalloc(reinterpret_cast<void**>(&d_in2), size);
#endif
in1 = reinterpret_cast<float16*>(malloc(size));
in2 = reinterpret_cast<float16*>(malloc(size));
out = reinterpret_cast<float16*>(malloc(size));
// right shift 1, mimic the unalignment of address
float16* r_in1 =
reinterpret_cast<float16*>(reinterpret_cast<uint8_t*>(in1) + shift_bit);
float16* r_in2 =
reinterpret_cast<float16*>(reinterpret_cast<uint8_t*>(in2) + shift_bit);
std::minstd_rand engine;
std::uniform_real_distribution<double> dist(0.0, 1.0);
for (size_t i = 0; i < num / 2; ++i) {
r_in1[i] = static_cast<float16>(dist(engine));
r_in2[i] = static_cast<float16>(dist(engine));
}
#ifdef PADDLE_WITH_HIP
hipMemcpy(d_in1, r_in1, array_size, hipMemcpyHostToDevice);
hipMemcpy(d_in2, r_in2, array_size, hipMemcpyHostToDevice);
hipLaunchKernelGGL(HIP_KERNEL_NAME(AddKernel<float16>),
dim3(1),
dim3(PADDLE_CUDA_NUM_THREADS),
0,
0,
d_in1,
d_in2,
num / 2);
hipDeviceSynchronize();
hipMemcpy(out, d_in2, array_size, hipMemcpyDeviceToHost);
hipDeviceSynchronize();
#else
cudaMemcpy(d_in1, r_in1, array_size, cudaMemcpyHostToDevice);
cudaMemcpy(d_in2, r_in2, array_size, cudaMemcpyHostToDevice);
AddKernel<float16><<<1, PADDLE_CUDA_NUM_THREADS>>>(d_in1, d_in2, num / 2);
cudaDeviceSynchronize();
cudaMemcpy(out, d_in2, array_size, cudaMemcpyDeviceToHost);
cudaDeviceSynchronize();
#endif
for (size_t i = 0; i < num / 2; ++i) {
// NOTE(dzhwinter): the float16 add has small truncate error.
// so we use EXPECT_NEAR to check the result.
EXPECT_NEAR(static_cast<float>(out[i]),
static_cast<float>(AddFunctor<float16>()(r_in1[i], r_in2[i])),
0.001);
}
free(in1);
free(in2);
free(out);
#ifdef PADDLE_WITH_HIP
hipFree(d_in1);
hipFree(d_in2);
#else
cudaFree(d_in1);
cudaFree(d_in2);
#endif
}
TEST(CudaAtomic, float16Unalign) {
// same with float16 testcase
TestUnalign(static_cast<size_t>(2), /*shift_bit*/ 2);
TestUnalign(static_cast<size_t>(1024), /*shift_bit*/ 2);
TestUnalign(static_cast<size_t>(1024 * 1024), /*shift_bit*/ 2);
// shift the address.
TestUnalign(static_cast<size_t>(2), /*shift_bit*/ 1);
TestUnalign(static_cast<size_t>(1024), /*shift_bit*/ 1);
TestUnalign(static_cast<size_t>(1024 * 1024), /*shift_bit*/ 1);
TestUnalign(static_cast<size_t>(2), /*shift_bit*/ 3);
TestUnalign(static_cast<size_t>(1024), /*shift_bit*/ 3);
TestUnalign(static_cast<size_t>(1024 * 1024), /*shift_bit*/ 3);
}
// https://devblogs.nvidia.com/faster-parallel-reductions-kepler/
template <typename T>
static __forceinline__ __device__ T WarpReduceSum(T val) {
unsigned mask = 0u;
CREATE_SHFL_MASK(mask, true);
for (int offset = warpSize / 2; offset > 0; offset /= 2) {
val += phi::backends::gpu::CudaShuffleDownSync(mask, val, offset);
}
return val;
}
template <typename T>
__forceinline__ __device__ T BlockReduce(T val) {
static __shared__ T shared[32]; // Shared mem for 32 partial sums
int lane = threadIdx.x % warpSize;
int wid = threadIdx.x / warpSize;
val = WarpReduceSum(val); // Each warp performs partial reduction
if (lane == 0) shared[wid] = val; // Write reduced value to shared memory
__syncthreads(); // Wait for all partial reductions
// read from shared memory only if that warp existed
val =
(threadIdx.x < blockDim.x / warpSize) ? shared[lane] : static_cast<T>(0);
if (wid == 0) val = WarpReduceSum(val); // Final reduce within first warp
return val;
}
template <typename T>
__global__ void DeviceReduceSum(T* in, T* out, size_t N) {
T sum(0);
CUDA_KERNEL_LOOP(i, N) { sum += in[i]; }
sum = BlockReduce<T>(sum);
__syncthreads();
if (threadIdx.x == 0) out[blockIdx.x] = sum;
}
template <typename T>
void TestReduce(size_t num, float atol = 0.01) {
T* in1;
T *d_in1, *d_in2;
size_t size = sizeof(T) * num;
#ifdef PADDLE_WITH_HIP
hipMalloc(reinterpret_cast<void**>(&d_in1), size);
hipMalloc(reinterpret_cast<void**>(&d_in2), sizeof(T));
#else
cudaMalloc(reinterpret_cast<void**>(&d_in1), size);
cudaMalloc(reinterpret_cast<void**>(&d_in2), sizeof(T));
#endif
in1 = reinterpret_cast<T*>(malloc(size));
std::minstd_rand engine;
std::uniform_real_distribution<double> dist(0.0, 1.0);
for (size_t i = 0; i < num; ++i) {
in1[i] = static_cast<T>(dist(engine));
}
auto out = std::accumulate(in1, in1 + num, static_cast<T>(0));
#ifdef PADDLE_WITH_HIP
hipMemcpy(d_in1, in1, size, hipMemcpyHostToDevice);
hipDeviceSynchronize();
hipLaunchKernelGGL(HIP_KERNEL_NAME(DeviceReduceSum<T>),
dim3(1),
dim3(PADDLE_CUDA_NUM_THREADS),
0,
0,
d_in1,
d_in2,
num);
hipMemcpy(in1, d_in2, sizeof(T), hipMemcpyDeviceToHost);
hipDeviceSynchronize();
#else
cudaMemcpy(d_in1, in1, size, cudaMemcpyHostToDevice);
cudaDeviceSynchronize();
DeviceReduceSum<T><<<1, PADDLE_CUDA_NUM_THREADS>>>(d_in1, d_in2, num);
cudaMemcpy(in1, d_in2, sizeof(T), cudaMemcpyDeviceToHost);
cudaDeviceSynchronize();
#endif
// NOTE(dzhwinter): the float16 add has small underflow/overflow
// so we use EXPECT_NEAR to check the result.
EXPECT_NEAR(static_cast<float>(in1[0]), static_cast<float>(out), atol);
free(in1);
#ifdef PADDLE_WITH_HIP
hipFree(d_in1);
hipFree(d_in2);
#else
cudaFree(d_in1);
cudaFree(d_in2);
#endif
}
TEST(CudaShuffleSync, float16) {
TestReduce<float>(10);
TestReduce<float>(1000);
// float16 will overflow or accumulate truncate errors in big size.
TestReduce<float16>(10);
TestReduce<float16>(100, /*atol error*/ 1.0);
}
@@ -0,0 +1,44 @@
// Copyright (c) 2019 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.
#include <gtest/gtest.h>
#include "paddle/phi/core/platform/device/gpu/gpu_dnn.h"
namespace paddle {
namespace platform {
TEST(TensorDescriptor, Empty) {
phi::backends::gpu::ActivationDescriptor a;
phi::backends::gpu::TensorDescriptor t;
phi::backends::gpu::TensorDescriptor t1;
phi::backends::gpu::TensorDescriptor *t11 =
new phi::backends::gpu::TensorDescriptor();
delete t11;
std::unique_ptr<phi::backends::gpu::TensorDescriptor> tt(
new phi::backends::gpu::TensorDescriptor());
}
TEST(TensorDescriptor, Normal) {
phi::DenseTensor tt;
tt.Resize({2, 3, 4});
tt.mutable_data<float>(phi::CPUPlace());
phi::backends::gpu::TensorDescriptor desc;
desc.set(tt);
EXPECT_TRUE(desc.desc() != nullptr);
}
} // namespace platform
} // namespace paddle
@@ -0,0 +1,4 @@
hip_test(
miopen_helper_test
SRCS miopen_helper_test.cc
DEPS phi common)
@@ -0,0 +1,92 @@
/* Copyright (c) 2020 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. */
#define GOOGLE_GLOG_DLL_DECL
#include <gtest/gtest.h>
#include "paddle/phi/core/platform/device/gpu/gpu_dnn.h"
TEST(MIOpenHelper, ScopedTensorDescriptor) {
using phi::DataLayout;
using phi::backends::gpu::ScopedTensorDescriptor;
ScopedTensorDescriptor tensor_desc;
std::vector<int> shape = {2, 4, 6, 6};
auto desc = tensor_desc.descriptor<float>(DataLayout::NCHW, shape);
miopenDataType_t type;
int nd;
std::vector<int> dims(4);
std::vector<int> strides(4);
phi::dynload::miopenGetTensorDescriptor(
desc, &type, dims.data(), strides.data());
phi::dynload::miopenGetTensorDescriptorSize(desc, &nd);
EXPECT_EQ(nd, 4);
for (size_t i = 0; i < dims.size(); ++i) {
EXPECT_EQ(dims[i], shape[i]);
}
EXPECT_EQ(strides[3], 1);
EXPECT_EQ(strides[2], 6);
EXPECT_EQ(strides[1], 36);
EXPECT_EQ(strides[0], 144);
// test tensor5d: ScopedTensorDescriptor
ScopedTensorDescriptor tensor5d_desc;
std::vector<int> shape_5d = {2, 4, 6, 6, 6};
auto desc_5d = tensor5d_desc.descriptor<float>(DataLayout::NCDHW, shape_5d);
std::vector<int> dims_5d(5);
std::vector<int> strides_5d(5);
phi::dynload::miopenGetTensorDescriptor(
desc_5d, &type, dims_5d.data(), strides_5d.data());
phi::dynload::miopenGetTensorDescriptorSize(desc_5d, &nd);
EXPECT_EQ(nd, 5);
for (size_t i = 0; i < dims_5d.size(); ++i) {
EXPECT_EQ(dims_5d[i], shape_5d[i]);
}
EXPECT_EQ(strides_5d[4], 1);
EXPECT_EQ(strides_5d[3], 6);
EXPECT_EQ(strides_5d[2], 36);
EXPECT_EQ(strides_5d[1], 216);
EXPECT_EQ(strides_5d[0], 864);
}
TEST(MIOpenHelper, ScopedConvolutionDescriptor) {
using phi::backends::gpu::ScopedConvolutionDescriptor;
ScopedConvolutionDescriptor conv_desc;
std::vector<int> src_pads = {2, 2, 2};
std::vector<int> src_strides = {1, 1, 1};
std::vector<int> src_dilations = {1, 1, 1};
auto desc = conv_desc.descriptor<float>(src_pads, src_strides, src_dilations);
miopenConvolutionMode_t mode;
int nd;
std::vector<int> pads(3);
std::vector<int> strides(3);
std::vector<int> dilations(3);
phi::dynload::miopenGetConvolutionNdDescriptor(
desc, 3, &nd, pads.data(), strides.data(), dilations.data(), &mode);
EXPECT_EQ(nd, 3);
for (size_t i = 0; i < src_pads.size(); ++i) {
EXPECT_EQ(pads[i], src_pads[i]);
EXPECT_EQ(strides[i], src_strides[i]);
EXPECT_EQ(dilations[i], src_dilations[i]);
}
EXPECT_EQ(mode, miopenConvolution);
}
+131
View File
@@ -0,0 +1,131 @@
/* Copyright (c) 2019 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. */
#include "paddle/phi/backends/device_code.h"
#include <utility>
#include "gtest/gtest.h"
#include "paddle/fluid/framework/lod_tensor.h"
#include "paddle/fluid/platform/init.h"
#ifdef PADDLE_WITH_CUDA
constexpr auto saxpy_code = R"(
extern "C" __global__
void saxpy_kernel(float a, float *x, float* y, float* z, size_t n) {
for (size_t tid = blockIdx.x * blockDim.x + threadIdx.x; tid < n;
tid += blockDim.x * gridDim.x) {
z[tid] = a * x[tid] + y[tid];
}
}
)";
#endif
#ifdef PADDLE_WITH_HIP
constexpr auto saxpy_code = R"(
#include <hip/hip_runtime.h>
extern "C" __global__
void saxpy_kernel(float a, float *x, float* y, float* z, size_t n) {
for (size_t tid = blockIdx.x * blockDim.x + threadIdx.x; tid < n;
tid += blockDim.x * gridDim.x) {
z[tid] = a * x[tid] + y[tid];
}
}
)";
#endif
#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP)
TEST(DeviceCode, cuda) {
if (!phi::dynload::HasNVRTC() || !phi::dynload::HasCUDADriver()) {
return;
}
paddle::framework::InitDevices({0});
phi::GPUPlace place = phi::GPUPlace(0);
phi::GPUDeviceCode code(place, "saxpy_kernel", saxpy_code);
phi::DenseTensor cpu_x;
phi::DenseTensor cpu_y;
phi::DenseTensor cpu_z;
float scale = 2;
auto dims = common::make_ddim(
{static_cast<int64_t>(256), static_cast<int64_t>(1024)});
phi::DeviceContextPool& pool = phi::DeviceContextPool::Instance();
auto* cpu_ctx = reinterpret_cast<phi::CPUContext*>(pool.Get(phi::CPUPlace()));
cpu_x.Resize(dims);
cpu_ctx->template Alloc<float>(&cpu_x);
cpu_y.Resize(dims);
cpu_ctx->template Alloc<float>(&cpu_y);
size_t n = cpu_x.numel();
for (size_t i = 0; i < n; ++i) {
cpu_x.data<float>()[i] = static_cast<float>(i);
}
for (size_t i = 0; i < n; ++i) {
cpu_y.data<float>()[i] = static_cast<float>(0.5);
}
phi::DenseTensor x;
phi::DenseTensor y;
phi::DenseTensor z;
auto* dev_ctx = reinterpret_cast<phi::GPUContext*>(pool.Get(place));
x.Resize(dims);
float* x_data = dev_ctx->template Alloc<float>(&x);
y.Resize(dims);
float* y_data = dev_ctx->template Alloc<float>(&y);
z.Resize(dims);
float* z_data = dev_ctx->template Alloc<float>(&z);
paddle::framework::TensorCopySync(cpu_x, place, &x);
paddle::framework::TensorCopySync(cpu_y, place, &y);
EXPECT_EQ(code.Compile(), true);
std::vector<void*> args = {&scale, &x_data, &y_data, &z_data, &n};
code.SetNumThreads(1024);
code.SetWorkloadPerThread(1);
code.Launch(n, &args);
dev_ctx->Wait();
paddle::framework::TensorCopySync(z, phi::CPUPlace(), &cpu_z);
for (size_t i = 0; i < n; i++) {
EXPECT_EQ(cpu_z.data<float>()[i], static_cast<float>(i) * scale + 0.5);
}
}
TEST(DeviceCodePool, cuda) {
if (!phi::dynload::HasNVRTC() || !phi::dynload::HasCUDADriver()) {
return;
}
paddle::framework::InitDevices({0});
phi::GPUPlace place = phi::GPUPlace(0);
phi::DeviceCodePool& pool = phi::DeviceCodePool::Init({place});
size_t num_device_codes_before = pool.size(place);
EXPECT_EQ(num_device_codes_before, 0UL);
std::unique_ptr<phi::DeviceCode> code(
new phi::GPUDeviceCode(place, "saxpy_kernel", saxpy_code));
LOG(INFO) << "origin ptr: " << code.get();
pool.Set(std::move(code));
size_t num_device_codes_after = pool.size(place);
EXPECT_EQ(num_device_codes_after, 1UL);
phi::DeviceCode* code_get = pool.Get(place, "saxpy_kernel");
LOG(INFO) << "get ptr: " << code_get;
}
#endif
@@ -0,0 +1,161 @@
/* Copyright (c) 2016 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. */
#include <vector>
#include "glog/logging.h"
#include "gtest/gtest.h"
#include "paddle/phi/core/dense_tensor.h"
#include "paddle/phi/core/memory/allocation/allocator_facade.h"
#include "paddle/phi/core/platform/device_context.h"
TEST(Device, Init) {
using phi::DeviceContext;
using phi::GPUContext;
using phi::GPUPlace;
int count = paddle::platform::GetGPUDeviceCount();
for (int i = 0; i < count; i++) {
phi::GPUContext* device_context = new phi::GPUContext(GPUPlace(i));
device_context->SetAllocator(
paddle::memory::allocation::AllocatorFacade::Instance()
.GetAllocator(GPUPlace(i), device_context->stream())
.get());
device_context->SetHostAllocator(
paddle::memory::allocation::AllocatorFacade::Instance()
.GetAllocator(phi::CPUPlace())
.get());
device_context->SetZeroAllocator(
paddle::memory::allocation::AllocatorFacade::Instance()
.GetZeroAllocator(GPUPlace(i))
.get());
device_context->SetHostZeroAllocator(
paddle::memory::allocation::AllocatorFacade::Instance()
.GetZeroAllocator(phi::CPUPlace())
.get());
device_context->SetPinnedAllocator(
paddle::memory::allocation::AllocatorFacade::Instance()
.GetAllocator(phi::GPUPinnedPlace())
.get());
device_context->PartialInitWithAllocator();
Eigen::GpuDevice* gpu_device = device_context->eigen_device();
ASSERT_NE(nullptr, gpu_device);
delete device_context;
}
}
TEST(Device, GPUContext) {
using phi::GPUContext;
using phi::GPUPlace;
int count = paddle::platform::GetGPUDeviceCount();
for (int i = 0; i < count; i++) {
phi::GPUContext* device_context = new phi::GPUContext(GPUPlace(i));
device_context->SetAllocator(
paddle::memory::allocation::AllocatorFacade::Instance()
.GetAllocator(GPUPlace(i), device_context->stream())
.get());
device_context->SetHostAllocator(
paddle::memory::allocation::AllocatorFacade::Instance()
.GetAllocator(phi::CPUPlace())
.get());
device_context->SetZeroAllocator(
paddle::memory::allocation::AllocatorFacade::Instance()
.GetZeroAllocator(GPUPlace(i))
.get());
device_context->SetHostZeroAllocator(
paddle::memory::allocation::AllocatorFacade::Instance()
.GetZeroAllocator(phi::CPUPlace())
.get());
device_context->SetPinnedAllocator(
paddle::memory::allocation::AllocatorFacade::Instance()
.GetAllocator(phi::GPUPinnedPlace())
.get());
device_context->PartialInitWithAllocator();
Eigen::GpuDevice* gpu_device = device_context->eigen_device();
ASSERT_NE(nullptr, gpu_device);
#ifdef PADDLE_WITH_HIP
miopenHandle_t cudnn_handle = device_context->cudnn_handle();
#else
cudnnHandle_t cudnn_handle = device_context->cudnn_handle();
#endif
ASSERT_NE(nullptr, cudnn_handle);
#ifdef PADDLE_WITH_HIP
rocblas_handle cublas_handle = device_context->cublas_handle();
#else
cublasHandle_t cublas_handle = device_context->cublas_handle();
#endif
ASSERT_NE(nullptr, cublas_handle);
delete device_context;
}
}
TEST(Device, HostZeroAllocator) {
using phi::GPUPlace;
auto device_context = std::make_unique<phi::GPUContext>(GPUPlace(0));
device_context->SetAllocator(
paddle::memory::allocation::AllocatorFacade::Instance()
.GetAllocator(GPUPlace(0), device_context->stream())
.get());
device_context->SetHostAllocator(
paddle::memory::allocation::AllocatorFacade::Instance()
.GetAllocator(phi::CPUPlace())
.get());
device_context->SetZeroAllocator(
paddle::memory::allocation::AllocatorFacade::Instance()
.GetZeroAllocator(GPUPlace(0))
.get());
device_context->SetHostZeroAllocator(
paddle::memory::allocation::AllocatorFacade::Instance()
.GetZeroAllocator(phi::CPUPlace())
.get());
device_context->SetPinnedAllocator(
paddle::memory::allocation::AllocatorFacade::Instance()
.GetAllocator(phi::GPUPinnedPlace())
.get());
device_context->PartialInitWithAllocator();
phi::DenseTensor tensor;
tensor.Resize({0});
device_context->HostAlloc<float>(&tensor);
ASSERT_EQ(tensor.place().GetType(), phi::AllocationType::CPU);
ASSERT_EQ(tensor.numel(), 0);
ASSERT_EQ(tensor.dtype(), phi::DataType::FLOAT32);
phi::GPUContext gpu_context(GPUPlace(0));
gpu_context.SetHostZeroAllocator(&device_context->GetHostZeroAllocator());
gpu_context.HostAlloc<float>(&tensor);
ASSERT_EQ(tensor.place().GetType(), phi::AllocationType::CPU);
}
TEST(Device, DeviceContextPool) {
using phi::CPUPlace;
using phi::DeviceContextPool;
using phi::GPUContext;
using phi::GPUPlace;
using phi::Place;
DeviceContextPool& pool = DeviceContextPool::Instance();
auto cpu_dev_ctx1 = pool.Get(CPUPlace());
auto cpu_dev_ctx2 = pool.Get(CPUPlace());
ASSERT_EQ(cpu_dev_ctx2, cpu_dev_ctx1);
std::vector<Place> gpu_places;
int count = paddle::platform::GetGPUDeviceCount();
for (int i = 0; i < count; ++i) {
auto dev_ctx = pool.Get(GPUPlace(i));
ASSERT_NE(dev_ctx, nullptr);
}
}
@@ -0,0 +1,40 @@
/* Copyright (c) 2022 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. */
#include "cuda.h" // NOLINT
#include "cuda_runtime.h" // NOLINT
#include "glog/logging.h"
#include "gtest/gtest.h"
#include "paddle/phi/core/memory/allocation/allocator_facade.h"
#include "paddle/phi/core/platform/cuda_graph_with_memory_pool.h"
#include "paddle/phi/core/platform/device_context.h"
#ifdef PADDLE_WITH_CUDA
TEST(Device, DeviceContextWithCUDAGraph) {
using phi::DeviceContext;
using phi::DeviceContextPool;
using phi::GPUContext;
using phi::GPUPlace;
using phi::Place;
DeviceContextPool& pool = DeviceContextPool::Instance();
Place place = GPUPlace(0);
auto* dev_ctx = pool.Get(place);
paddle::platform::BeginCUDAGraphCapture(
place, cudaStreamCaptureMode::cudaStreamCaptureModeThreadLocal, 0);
ASSERT_EQ(dev_ctx->IsCUDAGraphAllocatorValid(), true);
dev_ctx->GetCUDAGraphAllocator();
paddle::platform::EndCUDAGraphCapture();
ASSERT_EQ(dev_ctx->IsCUDAGraphAllocatorValid(), false);
}
#endif
@@ -0,0 +1,52 @@
/* Copyright (c) 2020 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. */
#include <vector>
#include "glog/logging.h"
#include "gtest/gtest.h"
#include "paddle/phi/core/platform/device_context.h"
TEST(Device, Init) {
using phi::DeviceContext;
using phi::XPUContext;
using phi::XPUPlace;
int count = paddle::platform::GetXPUDeviceCount();
for (int i = 0; i < count; i++) {
XPUContext* device_context = new XPUContext(XPUPlace(i));
xpu::Context* ctx = device_context->x_context();
ASSERT_NE(nullptr, ctx);
delete device_context;
}
}
TEST(Device, DeviceContextPool) {
using phi::CPUPlace;
using phi::DeviceContextPool;
using phi::Place;
using phi::XPUContext;
using phi::XPUPlace;
DeviceContextPool& pool = DeviceContextPool::Instance();
auto cpu_dev_ctx1 = pool.Get(CPUPlace());
auto cpu_dev_ctx2 = pool.Get(CPUPlace());
ASSERT_EQ(cpu_dev_ctx2, cpu_dev_ctx1);
std::vector<Place> xpu_places;
int count = paddle::platform::GetXPUDeviceCount();
for (int i = 0; i < count; ++i) {
auto dev_ctx = pool.Get(XPUPlace(i));
ASSERT_NE(dev_ctx, nullptr);
}
}
@@ -0,0 +1,147 @@
// Copyright (c) 2021 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.
#include "paddle/phi/core/platform/device_event.h"
#include "glog/logging.h"
#include "gtest/gtest.h"
#include "paddle/phi/common/place.h"
using ::paddle::platform::kCPU;
using ::paddle::platform::kCUDA;
using paddle::platform::DeviceEvent;
using phi::DeviceContextPool;
#ifdef PADDLE_WITH_CUDA
#include <cuda_runtime.h>
TEST(DeviceEvent, CUDA) {
VLOG(1) << "In Test";
using phi::GPUPlace;
auto& pool = DeviceContextPool::Instance();
auto place = GPUPlace(0);
auto* context = static_cast<phi::GPUContext*>(pool.Get(place));
ASSERT_NE(context, nullptr);
// case 1. test for event_creator
DeviceEvent event(place, paddle::platform::GenerateDeviceEventFlag());
ASSERT_NE(event.GetEvent().get(), nullptr);
bool status = event.Query();
ASSERT_EQ(status, true);
// case 2. test for event_recorder
event.Record(context);
// case 3. test for event_finisher
event.Finish();
status = event.Query();
ASSERT_EQ(status, true);
// case 4. test for event_waiter
float *src_fp32, *dst_fp32;
int size = 1000000 * sizeof(float);
cudaMallocHost(reinterpret_cast<void**>(&src_fp32), size);
cudaMalloc(reinterpret_cast<void**>(&dst_fp32), size);
cudaMemcpyAsync(
dst_fp32, src_fp32, size, cudaMemcpyHostToDevice, context->stream());
event.Record(context); // step 1. record it
status = event.Query();
ASSERT_EQ(status, false);
event.Wait(kCUDA, context); // step 2. add streamWaitEvent
status = event.Query();
ASSERT_EQ(status, false); // async
event.Wait(kCPU, context); // step 3. EventSynchronize
status = event.Query();
ASSERT_EQ(status, true); // sync
// release resource
cudaFree(dst_fp32);
cudaFreeHost(src_fp32);
}
#endif
#ifdef PADDLE_WITH_HIP
#include <hip/hip_runtime.h>
TEST(DeviceEvent, CUDA) {
VLOG(1) << "In Test";
using phi::GPUPlace;
auto& pool = DeviceContextPool::Instance();
auto place = GPUPlace(0);
auto* context = static_cast<phi::GPUContext*>(pool.Get(place));
ASSERT_NE(context, nullptr);
// case 1. test for event_creator
DeviceEvent event(place, paddle::platform::GenerateDeviceEventFlag());
ASSERT_NE(event.GetEvent().get(), nullptr);
bool status = event.Query();
ASSERT_EQ(status, true);
// case 2. test for event_recorder
event.Record(context);
status = event.Query();
ASSERT_EQ(status, false);
// case 3. test for event_finisher
event.Finish();
status = event.Query();
ASSERT_EQ(status, true);
// case 4. test for event_waiter
float *src_fp32, *dst_fp32;
int size = 1000000 * sizeof(float);
hipMallocHost(reinterpret_cast<void**>(&src_fp32), size);
hipMalloc(reinterpret_cast<void**>(&dst_fp32), size);
hipMemcpyAsync(
dst_fp32, src_fp32, size, hipMemcpyHostToDevice, context->stream());
event.Record(context); // step 1. record it
status = event.Query();
ASSERT_EQ(status, false);
event.Wait(kCUDA, context); // step 2. add streamWaitEvent
status = event.Query();
ASSERT_EQ(status, false); // async
event.Wait(kCPU, context); // step 3. EventSynchronize
status = event.Query();
ASSERT_EQ(status, true); // sync
// release resource
hipFree(dst_fp32);
hipFreeHost(src_fp32);
}
#endif
TEST(DeviceEvent, CPU) {
using phi::CPUPlace;
auto place = CPUPlace();
DeviceEvent event(place, paddle::platform::GenerateDeviceEventFlag());
auto& pool = DeviceContextPool::Instance();
auto* context = pool.Get(place);
// TODO(Aurelius84): All DeviceContext should has Record/Wait
event.Record(context);
event.SetFinished();
bool status = event.Query();
ASSERT_EQ(status, true);
// test for Record again
event.Record(context);
status = event.Query();
ASSERT_EQ(status, false); // SCHEDULED
event.Reset();
ASSERT_EQ(status, false); // INITIALIZED
}
+584
View File
@@ -0,0 +1,584 @@
/* Copyright (c) 2016 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. */
#include "paddle/fluid/platform/enforce.h"
#include <array>
#include <list>
#include "gtest/gtest.h"
TEST(ENFORCE, OK) {
PADDLE_ENFORCE(true,
common::errors::Unavailable(
"PADDLE_ENFORCE is ok %d now %f.", 123, 0.345));
size_t val = 1;
const size_t limit = 10;
PADDLE_ENFORCE(val < limit,
common::errors::Unavailable("PADDLE_ENFORCE tests failed."));
}
TEST(ENFORCE, FAILED) {
bool caught_exception = false;
try {
PADDLE_ENFORCE(false,
common::errors::Unavailable(
"PADDLE_ENFORCE won't work %d at all.", 123));
} catch (paddle::platform::EnforceNotMet& error) {
caught_exception = true;
std::string ex_msg = error.what();
EXPECT_TRUE(ex_msg.find("PADDLE_ENFORCE won't work 123 at all.") !=
std::string::npos);
}
EXPECT_TRUE(caught_exception);
caught_exception = false;
try {
PADDLE_ENFORCE(
false,
common::errors::Unavailable("PADDLE_ENFORCE won't work at all."));
} catch (paddle::platform::EnforceNotMet& error) {
caught_exception = true;
std::string ex_msg = error.what();
EXPECT_TRUE(ex_msg.find("PADDLE_ENFORCE won't work at all.") !=
std::string::npos);
}
EXPECT_TRUE(caught_exception);
caught_exception = false;
try {
PADDLE_ENFORCE(
false,
common::errors::Unavailable("PADDLE_ENFORCE won't work at all."));
} catch (paddle::platform::EnforceNotMet& error) {
caught_exception = true;
EXPECT_NE(std::string(error.what()).find(" at "), 0UL);
}
EXPECT_TRUE(caught_exception);
}
TEST(ENFORCE, NO_ARG_OK) {
int a = 2;
int b = 2;
PADDLE_ENFORCE_EQ(
a, b, common::errors::Unavailable("PADDLE_ENFORCE_EQ tests failed."));
// test enforce with extra message.
PADDLE_ENFORCE_EQ(a,
b,
common::errors::Unavailable(
"Some %s wrong in PADDLE_ENFORCE_EQ.", "info"));
}
TEST(ENFORCE_EQ, NO_EXTRA_MSG_FAIL) {
int a = 2;
bool caught_exception = false;
try {
PADDLE_ENFORCE_EQ(a,
1 + 3,
common::errors::InvalidArgument(
"The result is not equal correct result."));
} catch (paddle::platform::EnforceNotMet& error) {
caught_exception = true;
std::string ex_msg = error.what();
EXPECT_TRUE(ex_msg.find("Expected a == 1 + 3, but received a:2 != 1 "
"+ 3:4.") != std::string::npos);
}
EXPECT_TRUE(caught_exception);
}
TEST(ENFORCE_EQ, EXTRA_MSG_FAIL) {
int a = 2;
bool caught_exception = false;
try {
PADDLE_ENFORCE_EQ(a,
1 + 3,
common::errors::InvalidArgument(
"The result is not equal correct result."));
} catch (paddle::platform::EnforceNotMet& error) {
caught_exception = true;
std::string ex_msg = error.what();
EXPECT_TRUE(
ex_msg.find("Expected a == 1 + 3, but received a:2 != 1 + 3:4.") !=
std::string::npos);
}
EXPECT_TRUE(caught_exception);
}
TEST(ENFORCE_NE, OK) {
PADDLE_ENFORCE_NE(
1, 2, common::errors::Unavailable("PADDLE_ENFORCE_NE tests failed."));
PADDLE_ENFORCE_NE(
1.0, 2UL, common::errors::Unavailable("PADDLE_ENFORCE_NE tests failed."));
}
TEST(ENFORCE_NE, FAIL) {
bool caught_exception = false;
try {
// 2UL here to check data type compatible
PADDLE_ENFORCE_NE(1.0,
1UL,
common::errors::Unavailable(
"Expected 1.0 != 1UL, but received 1.0:1 == 1UL:1."));
} catch (paddle::platform::EnforceNotMet& error) {
caught_exception = true;
std::string ex_msg = error.what();
EXPECT_TRUE(ex_msg.find("Expected 1.0 != 1UL, but "
"received 1.0:1 == 1UL:1.") != std::string::npos);
}
EXPECT_TRUE(caught_exception);
}
TEST(ENFORCE_GT, OK) {
PADDLE_ENFORCE_GT(
2, 1, common::errors::Unavailable("PADDLE_ENFORCE_GT tests failed."));
}
TEST(ENFORCE_GT, FAIL) {
bool caught_exception = false;
try {
PADDLE_ENFORCE_GT(1,
2,
common::errors::InvalidArgument(
"Expected 1 > 2, but received 1:1 <= 2:2."));
} catch (paddle::platform::EnforceNotMet& error) {
caught_exception = true;
std::string ex_msg = error.what();
EXPECT_TRUE(ex_msg.find("Expected 1 > 2, but received 1:1 <= 2:2.") !=
std::string::npos);
}
EXPECT_TRUE(caught_exception);
}
TEST(ENFORCE_GE, OK) {
PADDLE_ENFORCE_GE(
2, 2, common::errors::Unavailable("PADDLE_ENFORCE_GE tests failed."));
PADDLE_ENFORCE_GE(
3, 2, common::errors::Unavailable("PADDLE_ENFORCE_GE tests failed."));
PADDLE_ENFORCE_GE(
3.21,
2.0,
common::errors::Unavailable("PADDLE_ENFORCE_GE tests failed."));
}
TEST(ENFORCE_GE, FAIL) {
bool caught_exception = false;
try {
PADDLE_ENFORCE_GE(1,
2,
common::errors::InvalidArgument(
"Expected 1 >= 2, but received 1:1 < 2:2."));
} catch (paddle::platform::EnforceNotMet& error) {
caught_exception = true;
std::string ex_msg = error.what();
EXPECT_TRUE(ex_msg.find("Expected 1 >= 2, but received 1:1 < 2:2.") !=
std::string::npos);
}
EXPECT_TRUE(caught_exception);
}
TEST(ENFORCE_LE, OK) {
PADDLE_ENFORCE_LE(
1, 1, common::errors::Unavailable("PADDLE_ENFORCE_LE tests failed."));
PADDLE_ENFORCE_LE(
1UL, 1UL, common::errors::Unavailable("PADDLE_ENFORCE_LE tests failed."));
PADDLE_ENFORCE_LE(
2, 3, common::errors::Unavailable("PADDLE_ENFORCE_LE tests failed."));
PADDLE_ENFORCE_LE(
2UL, 3UL, common::errors::Unavailable("PADDLE_ENFORCE_LE tests failed."));
PADDLE_ENFORCE_LE(
2.0, 3.2, common::errors::Unavailable("PADDLE_ENFORCE_LE tests failed."));
}
TEST(ENFORCE_LE, FAIL) {
bool caught_exception = false;
try {
PADDLE_ENFORCE_GT(1,
2,
common::errors::InvalidArgument(
"Expected 1 > 2, but received 1:1 <= 2:2."));
} catch (paddle::platform::EnforceNotMet& error) {
caught_exception = true;
std::string ex_msg = error.what();
EXPECT_TRUE(ex_msg.find("Expected 1 > 2, but received 1:1 <= 2:2.") !=
std::string::npos);
}
EXPECT_TRUE(caught_exception);
}
TEST(ENFORCE_LT, OK) {
PADDLE_ENFORCE_LT(
3, 10, common::errors::Unavailable("PADDLE_ENFORCE_LT tests failed."));
PADDLE_ENFORCE_LT(
2UL, 3UL, common::errors::Unavailable("PADDLE_ENFORCE_LT tests failed."));
PADDLE_ENFORCE_LT(
2, 3, common::errors::Unavailable("PADDLE_ENFORCE_LT tests failed."));
}
TEST(ENFORCE_LT, FAIL) {
bool caught_exception = false;
try {
PADDLE_ENFORCE_LT(
1UL,
0.12,
common::errors::InvalidArgument(
"Expected 1UL < 0.12, but received 1UL:1 >= 0.12:0.12."));
} catch (paddle::platform::EnforceNotMet& error) {
caught_exception = true;
std::string ex_msg = error.what();
EXPECT_TRUE(ex_msg.find("Expected 1UL < 0.12, but "
"received 1UL:1 >= 0.12:0.12.") !=
std::string::npos);
}
EXPECT_TRUE(caught_exception);
}
TEST(ENFORCE_NOT_NULL, OK) {
int* a = new int;
PADDLE_ENFORCE_NOT_NULL(
a, common::errors::Unavailable("PADDLE_ENFORCE_NOT_NULL tests failed."));
delete a;
}
TEST(ENFORCE_NOT_NULL, FAIL) {
bool caught_exception = false;
try {
int* a = nullptr;
PADDLE_ENFORCE_NOT_NULL(
a, common::errors::Unavailable("The a should not be null."));
} catch (paddle::platform::EnforceNotMet& error) {
caught_exception = true;
std::string ex_msg = error.what();
EXPECT_TRUE(ex_msg.find("The a should not be null.") != std::string::npos);
}
EXPECT_TRUE(caught_exception);
}
struct Dims {
std::array<size_t, 4> dims_;
bool operator==(const Dims& o) const {
for (size_t i = 0; i < 4; ++i) {
if (dims_[i] != o.dims_[i]) return false;
}
return true;
}
};
std::ostream& operator<<(std::ostream& os, const Dims& d) {
for (size_t i = 0; i < 4; ++i) {
if (i == 0) {
os << "[";
}
os << d.dims_[i];
if (i == 4 - 1) {
os << "]";
} else {
os << ", ";
}
}
return os;
}
TEST(ENFORCE_USER_DEFINED_CLASS, EQ) {
Dims a{{1, 2, 3, 4}}, b{{1, 2, 3, 4}};
PADDLE_ENFORCE_EQ(
a, b, common::errors::Unavailable("PADDLE_ENFORCE_EQ tests failed."));
}
TEST(ENFORCE_USER_DEFINED_CLASS, NE) {
Dims a{{1, 2, 3, 4}}, b{{5, 6, 7, 8}};
bool caught_exception = false;
try {
PADDLE_ENFORCE_EQ(
a, b, common::errors::Unavailable("PADDLE_ENFORCE_EQ tests failed."));
} catch (paddle::platform::EnforceNotMet&) {
caught_exception = true;
}
EXPECT_TRUE(caught_exception);
}
TEST(EOF_EXCEPTION, THROW_EOF) {
bool caught_eof = false;
try {
PADDLE_THROW_EOF();
} catch (paddle::platform::EOFException& error) {
caught_eof = true;
std::string ex_msg = error.what();
EXPECT_TRUE(ex_msg.find("There is no next data.") != std::string::npos);
}
EXPECT_TRUE(caught_eof);
}
#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP)
template <typename T>
bool CheckCudaStatusSuccess(T value, const std::string& msg = "success") {
PADDLE_ENFORCE_GPU_SUCCESS(value);
return true;
}
template <typename T>
bool CheckCudaStatusFailure(T value, const std::string& msg) {
try {
PADDLE_ENFORCE_GPU_SUCCESS(value);
return false;
} catch (paddle::platform::EnforceNotMet& error) {
std::string ex_msg = error.what();
std::cout << ex_msg << std::endl;
return ex_msg.find(msg) != std::string::npos;
}
}
#ifdef PADDLE_WITH_HIP
TEST(enforce, hip_success) {
EXPECT_TRUE(CheckCudaStatusSuccess(hipSuccess));
EXPECT_TRUE(CheckCudaStatusFailure(hipErrorInvalidValue, "Hip error"));
EXPECT_TRUE(CheckCudaStatusFailure(hipErrorOutOfMemory, "Hip error"));
EXPECT_TRUE(CheckCudaStatusSuccess(HIPRAND_STATUS_SUCCESS));
EXPECT_TRUE(
CheckCudaStatusFailure(HIPRAND_STATUS_VERSION_MISMATCH, "Hiprand error"));
EXPECT_TRUE(
CheckCudaStatusFailure(HIPRAND_STATUS_NOT_INITIALIZED, "Hiprand error"));
EXPECT_TRUE(CheckCudaStatusSuccess(miopenStatusSuccess));
EXPECT_TRUE(
CheckCudaStatusFailure(miopenStatusNotInitialized, "Miopen error"));
EXPECT_TRUE(CheckCudaStatusFailure(miopenStatusAllocFailed, "Miopen error"));
EXPECT_TRUE(CheckCudaStatusSuccess(rocblas_status_success));
EXPECT_TRUE(
CheckCudaStatusFailure(rocblas_status_invalid_handle, "Rocblas error"));
EXPECT_TRUE(
CheckCudaStatusFailure(rocblas_status_invalid_value, "Rocblas error"));
EXPECT_TRUE(CheckCudaStatusSuccess(HIPFFT_SUCCESS));
EXPECT_TRUE(CheckCudaStatusFailure(HIPFFT_INVALID_PLAN, "HIPFFT error"));
EXPECT_TRUE(CheckCudaStatusFailure(HIPFFT_ALLOC_FAILED, "HIPFFT error"));
#if !defined(__APPLE__) && defined(PADDLE_WITH_RCCL)
EXPECT_TRUE(CheckCudaStatusSuccess(ncclSuccess));
EXPECT_TRUE(CheckCudaStatusFailure(ncclUnhandledCudaError, "Rccl error"));
EXPECT_TRUE(CheckCudaStatusFailure(ncclSystemError, "Rccl error"));
#endif
}
#else
TEST(enforce, cuda_success) {
EXPECT_TRUE(CheckCudaStatusSuccess(cudaSuccess));
EXPECT_TRUE(CheckCudaStatusFailure(cudaErrorInvalidValue, "CUDA error"));
EXPECT_TRUE(CheckCudaStatusFailure(cudaErrorMemoryAllocation, "CUDA error"));
EXPECT_TRUE(
CheckCudaStatusFailure(cudaErrorInsufficientDriver, "CUDA error"));
EXPECT_TRUE(
CheckCudaStatusFailure(cudaErrorContextIsDestroyed, "CUDA error"));
EXPECT_TRUE(CheckCudaStatusSuccess(CURAND_STATUS_SUCCESS));
EXPECT_TRUE(
CheckCudaStatusFailure(CURAND_STATUS_VERSION_MISMATCH, "CURAND error"));
EXPECT_TRUE(
CheckCudaStatusFailure(CURAND_STATUS_NOT_INITIALIZED, "CURAND error"));
EXPECT_TRUE(
CheckCudaStatusFailure(CURAND_STATUS_ARCH_MISMATCH, "CURAND error"));
EXPECT_TRUE(CheckCudaStatusFailure(CURAND_STATUS_LENGTH_NOT_MULTIPLE,
"CURAND error"));
EXPECT_TRUE(CheckCudaStatusSuccess(CUDNN_STATUS_SUCCESS));
EXPECT_TRUE(
CheckCudaStatusFailure(CUDNN_STATUS_NOT_INITIALIZED, "CUDNN error"));
EXPECT_TRUE(CheckCudaStatusFailure(CUDNN_STATUS_ALLOC_FAILED, "CUDNN error"));
EXPECT_TRUE(CheckCudaStatusFailure(CUDNN_STATUS_BAD_PARAM, "CUDNN error"));
EXPECT_TRUE(
CheckCudaStatusFailure(CUDNN_STATUS_LICENSE_ERROR, "CUDNN error"));
EXPECT_TRUE(CheckCudaStatusSuccess(CUBLAS_STATUS_SUCCESS));
EXPECT_TRUE(
CheckCudaStatusFailure(CUBLAS_STATUS_NOT_INITIALIZED, "CUBLAS error"));
EXPECT_TRUE(
CheckCudaStatusFailure(CUBLAS_STATUS_INVALID_VALUE, "CUBLAS error"));
EXPECT_TRUE(
CheckCudaStatusFailure(CUBLAS_STATUS_EXECUTION_FAILED, "CUBLAS error"));
EXPECT_TRUE(
CheckCudaStatusFailure(CUBLAS_STATUS_MAPPING_ERROR, "CUBLAS error"));
EXPECT_TRUE(CheckCudaStatusSuccess(CUSOLVER_STATUS_SUCCESS));
EXPECT_TRUE(CheckCudaStatusFailure(CUSOLVER_STATUS_NOT_INITIALIZED,
"CUSOLVER error"));
EXPECT_TRUE(
CheckCudaStatusFailure(CUSOLVER_STATUS_ALLOC_FAILED, "CUSOLVER error"));
EXPECT_TRUE(
CheckCudaStatusFailure(CUSOLVER_STATUS_INTERNAL_ERROR, "CUSOLVER error"));
EXPECT_TRUE(
CheckCudaStatusFailure(CUSOLVER_STATUS_INVALID_VALUE, "CUSOLVER error"));
EXPECT_TRUE(CheckCudaStatusSuccess(CUFFT_SUCCESS));
EXPECT_TRUE(CheckCudaStatusFailure(CUFFT_INVALID_PLAN, "CUFFT error"));
EXPECT_TRUE(CheckCudaStatusFailure(CUFFT_ALLOC_FAILED, "CUFFT error"));
EXPECT_TRUE(CheckCudaStatusFailure(CUFFT_INVALID_TYPE, "CUFFT error"));
EXPECT_TRUE(CheckCudaStatusFailure(CUFFT_INVALID_VALUE, "CUFFT error"));
EXPECT_TRUE(CheckCudaStatusFailure(CUFFT_INTERNAL_ERROR, "CUFFT error"));
EXPECT_TRUE(CheckCudaStatusFailure(CUFFT_EXEC_FAILED, "CUFFT error"));
EXPECT_TRUE(CheckCudaStatusFailure(CUFFT_SETUP_FAILED, "CUFFT error"));
EXPECT_TRUE(CheckCudaStatusFailure(CUFFT_INVALID_SIZE, "CUFFT error"));
EXPECT_TRUE(CheckCudaStatusFailure(CUFFT_UNALIGNED_DATA, "CUFFT error"));
#ifdef CUFFT_INCOMPLETE_PARAMETER_LIST
EXPECT_TRUE(
CheckCudaStatusFailure(CUFFT_INCOMPLETE_PARAMETER_LIST, "CUFFT error"));
#endif
EXPECT_TRUE(CheckCudaStatusFailure(CUFFT_INVALID_DEVICE, "CUFFT error"));
#ifdef CUFFT_PARSE_ERROR
EXPECT_TRUE(CheckCudaStatusFailure(CUFFT_PARSE_ERROR, "CUFFT error"));
#endif
EXPECT_TRUE(CheckCudaStatusFailure(CUFFT_NO_WORKSPACE, "CUFFT error"));
EXPECT_TRUE(CheckCudaStatusFailure(CUFFT_NOT_IMPLEMENTED, "CUFFT error"));
#ifdef CUFFT_LICENSE_ERROR
EXPECT_TRUE(CheckCudaStatusFailure(CUFFT_LICENSE_ERROR, "CUFFT error"));
#endif
EXPECT_TRUE(CheckCudaStatusFailure(CUFFT_NOT_SUPPORTED, "CUFFT error"));
#if !defined(__APPLE__) && defined(PADDLE_WITH_NCCL)
EXPECT_TRUE(CheckCudaStatusSuccess(ncclSuccess));
EXPECT_TRUE(CheckCudaStatusFailure(ncclUnhandledCudaError, "NCCL error"));
EXPECT_TRUE(CheckCudaStatusFailure(ncclSystemError, "NCCL error"));
EXPECT_TRUE(CheckCudaStatusFailure(ncclInternalError,
"An internal check failed. This is either "
"a bug in NCCL or due to memory "
"corruption"));
EXPECT_TRUE(CheckCudaStatusFailure(ncclInvalidUsage,
"The call to NCCL is incorrect. This is "
"usually reflecting a programming error"));
#endif
}
#endif
#endif
struct CannotToStringType {
explicit CannotToStringType(int num) : num_(num) {}
bool operator==(const CannotToStringType& other) const {
return num_ == other.num_;
}
bool operator!=(const CannotToStringType& other) const {
return num_ != other.num_;
}
private:
int num_;
};
TEST(enforce, cannot_to_string_type) {
static_assert(
!common::enforce::details::CanToString<CannotToStringType>::kValue,
"CannotToStringType must not be converted to string");
static_assert(common::enforce::details::CanToString<int>::kValue,
"int can be converted to string");
CannotToStringType obj1(3), obj2(4), obj3(3);
PADDLE_ENFORCE_NE(
obj1,
obj2,
common::errors::InvalidArgument("Object 1 is not equal to Object 2"));
PADDLE_ENFORCE_EQ(
obj1,
obj3,
common::errors::InvalidArgument("Object 1 is equal to Object 3"));
std::string msg = "Compare obj1 with obj2";
try {
PADDLE_ENFORCE_EQ(obj1, obj2, common::errors::InvalidArgument(msg));
} catch (paddle::platform::EnforceNotMet& error) {
std::string ex_msg = error.what();
LOG(INFO) << ex_msg;
EXPECT_TRUE(ex_msg.find(msg) != std::string::npos);
EXPECT_TRUE(
ex_msg.find("Expected obj1 == obj2, but received obj1 != obj2") !=
std::string::npos);
}
msg = "Compare x with y";
try {
int x = 3, y = 2;
PADDLE_ENFORCE_EQ(x, y, common::errors::InvalidArgument(msg));
} catch (paddle::platform::EnforceNotMet& error) {
std::string ex_msg = error.what();
LOG(INFO) << ex_msg;
EXPECT_TRUE(ex_msg.find(msg) != std::string::npos);
EXPECT_TRUE(ex_msg.find("Expected x == y, but received x:3 != y:2") !=
std::string::npos);
}
std::set<int> set;
PADDLE_ENFORCE_EQ(set.begin(),
set.end(),
common::errors::InvalidArgument(
"The begin and end of set is not equal."));
set.insert(3);
PADDLE_ENFORCE_NE(
set.begin(),
set.end(),
common::errors::InvalidArgument("The begin and end of set is equal."));
std::list<float> list;
PADDLE_ENFORCE_EQ(list.begin(),
list.end(),
common::errors::InvalidArgument(
"The begin and end of list is not equal."));
list.push_back(4);
PADDLE_ENFORCE_NE(
list.begin(),
list.end(),
common::errors::InvalidArgument("The begin and end of list is equal."));
}
TEST(GET_DATA_SAFELY_MACRO, SUCCESS) {
int* a = new int(10); // NOLINT
GET_DATA_SAFELY(a, "Input", "X", "dummy");
delete a;
}
#ifndef _WIN32
TEST(GET_DATA_SAFELY_MACRO, FAIL) {
bool caught_exception = false;
try {
int* a = nullptr;
GET_DATA_SAFELY(a, "Input", "X", "dummy");
} catch (paddle::platform::EnforceNotMet& error) {
caught_exception = true;
}
EXPECT_TRUE(caught_exception);
}
#endif
TEST(OP_INOUT_CHECK_MACRO, SUCCESS) {
OP_INOUT_CHECK(true, "Input", "X", "dummy");
}
TEST(OP_INOUT_CHECK_MACRO, FAIL) {
bool caught_exception = false;
try {
OP_INOUT_CHECK(false, "Input", "X", "dummy");
} catch (paddle::platform::EnforceNotMet& error) {
caught_exception = true;
}
EXPECT_TRUE(caught_exception);
}
TEST(PADDLE_GET_SAFELY, SUCCESS) {
paddle::framework::Attribute attr;
attr = true;
bool rlt = PADDLE_GET(bool, attr);
EXPECT_EQ(rlt, true);
}
TEST(PADDLE_GET_SAFELY, FAIL) {
paddle::framework::Attribute attr;
attr = true;
bool caught_exception = false;
try {
PADDLE_GET(int, attr);
} catch (paddle::platform::EnforceNotMet& error) {
caught_exception = true;
}
EXPECT_TRUE(caught_exception);
}
+119
View File
@@ -0,0 +1,119 @@
/* Copyright (c) 2019 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. */
#include "paddle/common/errors.h"
#include <string>
#include "gtest/gtest.h"
#include "paddle/fluid/platform/enforce.h"
using namespace common::errors; // NOLINT
#define CHECK_PADDLE_THROW(EFUNC) \
do { \
bool caught_exception = false; \
try { \
PADDLE_THROW((EFUNC)("paddle throw test.")); \
} catch (paddle::platform::EnforceNotMet & error) { \
caught_exception = true; \
std::string ex_msg = error.what(); \
EXPECT_TRUE(ex_msg.find("paddle throw test.") != std::string::npos); \
} \
EXPECT_TRUE(caught_exception); \
} while (0)
#define CHECK_PADDLE_ENFORCE(EFUNC) \
do { \
bool caught_exception = false; \
try { \
PADDLE_ENFORCE(false, (EFUNC)("paddle enforce test.")); \
} catch (paddle::platform::EnforceNotMet & error) { \
caught_exception = true; \
std::string ex_msg = error.what(); \
EXPECT_TRUE(ex_msg.find("paddle enforce test.") != std::string::npos); \
} \
EXPECT_TRUE(caught_exception); \
} while (0)
#define CHECK_PADDLE_ENFORCE_NOT_NULL(EFUNC) \
do { \
bool caught_exception = false; \
try { \
PADDLE_ENFORCE_NOT_NULL(nullptr, \
(EFUNC)("paddle enforce not null test.")); \
} catch (paddle::platform::EnforceNotMet & error) { \
caught_exception = true; \
std::string ex_msg = error.what(); \
EXPECT_TRUE(ex_msg.find("paddle enforce not null test.") != \
std::string::npos); \
} \
EXPECT_TRUE(caught_exception); \
} while (0)
#define CHECK_PADDLE_ENFORCE_EQ(EFUNC) \
do { \
bool caught_exception = false; \
try { \
PADDLE_ENFORCE_EQ(1, 2, (EFUNC)("paddle enforce equal test.")); \
} catch (paddle::platform::EnforceNotMet & error) { \
caught_exception = true; \
std::string ex_msg = error.what(); \
EXPECT_TRUE(ex_msg.find("paddle enforce equal test.") != \
std::string::npos); \
} \
EXPECT_TRUE(caught_exception); \
} while (0)
#define CHECK_ALL_PADDLE_EXCEPTION_MACRO(EFUNC) \
do { \
CHECK_PADDLE_THROW(EFUNC); \
CHECK_PADDLE_ENFORCE(EFUNC); \
CHECK_PADDLE_ENFORCE_NOT_NULL(EFUNC); \
CHECK_PADDLE_ENFORCE_EQ(EFUNC); \
} while (0)
TEST(Errors, InvalidArgument) {
CHECK_ALL_PADDLE_EXCEPTION_MACRO(InvalidArgument);
}
TEST(Errors, NotFound) { CHECK_ALL_PADDLE_EXCEPTION_MACRO(NotFound); }
TEST(Errors, OutOfRange) { CHECK_ALL_PADDLE_EXCEPTION_MACRO(OutOfRange); }
TEST(Errors, AlreadyExists) { CHECK_ALL_PADDLE_EXCEPTION_MACRO(AlreadyExists); }
TEST(Errors, ResourceExhausted) {
CHECK_ALL_PADDLE_EXCEPTION_MACRO(ResourceExhausted);
}
TEST(Errors, PreconditionNotMet) {
CHECK_ALL_PADDLE_EXCEPTION_MACRO(PreconditionNotMet);
}
TEST(Errors, PermissionDenied) {
CHECK_ALL_PADDLE_EXCEPTION_MACRO(PermissionDenied);
}
TEST(Errors, ExecutionTimeout) {
CHECK_ALL_PADDLE_EXCEPTION_MACRO(ExecutionTimeout);
}
TEST(Errors, Unimplemented) { CHECK_ALL_PADDLE_EXCEPTION_MACRO(Unimplemented); }
TEST(Errors, Unavailable) { CHECK_ALL_PADDLE_EXCEPTION_MACRO(Unavailable); }
TEST(Errors, Fatal) { CHECK_ALL_PADDLE_EXCEPTION_MACRO(Fatal); }
TEST(Errors, External) { CHECK_ALL_PADDLE_EXCEPTION_MACRO(External); }
+170
View File
@@ -0,0 +1,170 @@
/* Copyright (c) 2016 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. */
#include "paddle/phi/common/float16.h"
#include "gtest/gtest.h"
#include "paddle/fluid/framework/lod_tensor.h"
#include "paddle/fluid/platform/enforce.h"
#include "paddle/phi/kernels/funcs/eigen/extensions.h"
namespace paddle {
namespace platform {
using float16 = phi::dtype::float16;
using namespace phi::dtype; // NOLINT
TEST(float16, conversion_cpu) {
// Conversion from float
EXPECT_EQ(float16(1.0f).x, 0x3c00);
EXPECT_EQ(float16(0.5f).x, 0x3800);
EXPECT_EQ(float16(0.33333f).x, 0x3555);
EXPECT_EQ(float16(0.0f).x, 0x0000);
EXPECT_EQ(float16(-0.0f).x, 0x8000);
EXPECT_EQ(float16(65504.0f).x, 0x7bff);
EXPECT_EQ(float16(65536.0f).x, 0x7c00);
// Conversion from double
EXPECT_EQ(float16(1.0).x, 0x3c00);
EXPECT_EQ(float16(0.5).x, 0x3800);
EXPECT_EQ(float16(0.33333).x, 0x3555);
EXPECT_EQ(float16(0.0).x, 0x0000);
EXPECT_EQ(float16(-0.0).x, 0x8000);
EXPECT_EQ(float16(65504.0).x, 0x7bff);
EXPECT_EQ(float16(65536.0).x, 0x7c00);
// Conversion from int
EXPECT_EQ(float16(-1).x, 0xbc00);
EXPECT_EQ(float16(0).x, 0x0000);
EXPECT_EQ(float16(1).x, 0x3c00);
EXPECT_EQ(float16(2).x, 0x4000);
EXPECT_EQ(float16(3).x, 0x4200);
// Conversion from bool
EXPECT_EQ(float16(true).x, 0x3c00);
EXPECT_EQ(float16(false).x, 0x0000);
// Assignment operator
float16 v_assign;
v_assign = float16(0);
EXPECT_EQ(v_assign.x, 0x0000);
v_assign = 0.5f;
EXPECT_EQ(v_assign.x, 0x3800);
v_assign = 0.33333;
EXPECT_EQ(v_assign.x, 0x3555);
v_assign = -1;
EXPECT_EQ(v_assign.x, 0xbc00);
v_assign = true;
EXPECT_EQ(v_assign.x, 0x3c00);
// Conversion operator
EXPECT_EQ(static_cast<float>(float16(0.5f)), 0.5f);
EXPECT_NEAR(static_cast<double>(float16(0.33333)), 0.33333, 0.0001);
EXPECT_EQ(static_cast<int>(float16(-1)), -1);
EXPECT_EQ(static_cast<bool>(float16(true)), true);
}
TEST(float16, arithmetic_cpu) {
EXPECT_EQ(static_cast<float>(float16(1) + float16(1)), 2);
EXPECT_EQ(static_cast<float>(float16(5) + float16(-5)), 0);
EXPECT_NEAR(
static_cast<float>(float16(0.33333f) + float16(0.66667f)), 1.0f, 0.001);
EXPECT_EQ(static_cast<float>(float16(3) - float16(5)), -2);
EXPECT_NEAR(static_cast<float>(float16(0.66667f) - float16(0.33333f)),
0.33334f,
0.001);
EXPECT_NEAR(static_cast<float>(float16(3.3f) * float16(2.0f)), 6.6f, 0.01);
EXPECT_NEAR(static_cast<float>(float16(-2.1f) * float16(-3.0f)), 6.3f, 0.01);
EXPECT_NEAR(
static_cast<float>(float16(2.0f) / float16(3.0f)), 0.66667f, 0.001);
EXPECT_EQ(static_cast<float>(float16(1.0f) / float16(2.0f)), 0.5f);
EXPECT_EQ(static_cast<float>(-float16(512.0f)), -512.0f);
EXPECT_EQ(static_cast<float>(-float16(-512.0f)), 512.0f);
}
TEST(float16, comparison_cpu) {
EXPECT_TRUE(float16(1.0f) == float16(1.0f));
EXPECT_FALSE(float16(-1.0f) == float16(-0.5f));
EXPECT_TRUE(float16(1.0f) != float16(0.5f));
EXPECT_FALSE(float16(-1.0f) != float16(-1.0f));
EXPECT_TRUE(float16(1.0f) < float16(2.0f));
EXPECT_FALSE(float16(-1.0f) < float16(-1.0f));
EXPECT_TRUE(float16(1.0f) <= float16(1.0f));
EXPECT_TRUE(float16(2.0f) > float16(1.0f));
EXPECT_FALSE(float16(-2.0f) > float16(-2.0f));
EXPECT_TRUE(float16(2.0f) >= float16(2.0f));
EXPECT_TRUE(float16(0.0f) == float16(-0.0f));
EXPECT_TRUE(float16(0.0f) <= float16(-0.0f));
EXPECT_TRUE(float16(0.0f) >= float16(-0.0f));
EXPECT_FALSE(float16(0.0f) < float16(-0.0f));
EXPECT_FALSE(float16(-0.0f) < float16(0.0f));
EXPECT_FALSE(float16(0.0f) > float16(-0.0f));
EXPECT_FALSE(float16(-0.0f) > float16(0.0f));
}
TEST(float16, lod_tensor_cpu) {
phi::DenseTensor lod_tensor;
std::vector<float16> input_data = {
float16(1.0f), float16(0.5f), float16(0.33333f), float16(0.0f)};
EXPECT_EQ(input_data[0].x, 0x3c00);
EXPECT_EQ(input_data[1].x, 0x3800);
EXPECT_EQ(input_data[2].x, 0x3555);
EXPECT_EQ(input_data[3].x, 0x0000);
lod_tensor.Resize({4, 1});
lod_tensor.set_lod(phi::LegacyLoD({{0, 2, 4}}));
float16* data_ptr = lod_tensor.mutable_data<float16>(CPUPlace());
EXPECT_NE(data_ptr, nullptr);
EXPECT_EQ(input_data.size(), static_cast<size_t>(lod_tensor.numel()));
for (size_t i = 0; i < input_data.size(); ++i) {
data_ptr[i] = input_data[i];
EXPECT_EQ(data_ptr[i].x, input_data[i].x);
}
}
TEST(float16, floating) {
// compile time assert.
PADDLE_ENFORCE_EQ(
std::is_floating_point<float16>::value,
true,
common::errors::Unavailable("The float16 support in CPU failed."));
}
TEST(float16, print) {
float16 a = float16(1.0f);
std::cout << a << std::endl;
}
// CPU test
TEST(float16, isinf) {
float16 a;
a.x = 0x7c00;
float16 b = float16(INFINITY);
float16 c = static_cast<float16>(INFINITY);
EXPECT_EQ(std::isinf(a), true);
EXPECT_EQ(std::isinf(b), true);
EXPECT_EQ(std::isinf(c), true);
}
TEST(float16, isnan) {
float16 a;
a.x = 0x7fff;
float16 b = float16(NAN);
float16 c = static_cast<float16>(NAN);
EXPECT_EQ(std::isnan(a), true);
EXPECT_EQ(std::isnan(b), true);
EXPECT_EQ(std::isnan(c), true);
}
} // namespace platform
} // namespace paddle
+426
View File
@@ -0,0 +1,426 @@
/* Copyright (c) 2016 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. */
#include "paddle/phi/common/float16.h"
#include <glog/logging.h>
#include <gtest/gtest.h>
#include <bitset>
#include <iostream>
#include "paddle/fluid/framework/lod_tensor.h"
#include "paddle/fluid/framework/tensor_util.h"
#include "paddle/fluid/platform/enforce.h"
#include "paddle/phi/kernels/funcs/eigen/extensions.h"
#define ARITHMETIC_KERNEL(op_type, sign) \
__global__ void op_type(const half *in1, const half *in2, half *out) { \
out[0] = in1[0] sign in2[0]; \
}
#define COMPOUND_KERNEL(op_type, sign) \
__global__ void op_type(half *in1, const half *in2) { in1[0] sign in2[0]; }
#define COMPARISON_KERNEL(op_type, sign) \
__global__ void op_type(const half *in1, const half *in2, bool *out) { \
out[0] = in1[0] sign in2[0]; \
}
#ifdef PADDLE_WITH_HIP
#define ARITHMETIC_KERNEL_LAUNCH(op_type) \
void Test##op_type(float v_in1, float v_in2, float v_out) { \
LOG(INFO) << "Test " << #op_type << " on GPU!"; \
half *in1, *in2, *out; \
half *d_in1, *d_in2, *d_out; \
int size = sizeof(half); \
hipMalloc(reinterpret_cast<void **>(&d_in1), size); \
hipMalloc(reinterpret_cast<void **>(&d_in2), size); \
hipMalloc(reinterpret_cast<void **>(&d_out), size); \
in1 = reinterpret_cast<half *>(malloc(size)); \
in2 = reinterpret_cast<half *>(malloc(size)); \
out = reinterpret_cast<half *>(malloc(size)); \
in1[0] = float16(v_in1).to_half(); \
in2[0] = float16(v_in2).to_half(); \
hipMemcpy(d_in1, in1, size, hipMemcpyHostToDevice); \
hipMemcpy(d_in2, in2, size, hipMemcpyHostToDevice); \
hipLaunchKernelGGL(op_type, dim3(1), dim3(1), 0, 0, d_in1, d_in2, d_out); \
hipMemcpy(out, d_out, size, hipMemcpyDeviceToHost); \
EXPECT_EQ(static_cast<float>(float16(out[0])), v_out); \
free(in1); \
free(in2); \
free(out); \
hipFree(d_in1); \
hipFree(d_in2); \
hipFree(d_out); \
}
#define COMPOUND_KERNEL_LAUNCH(op_type) \
void Test##op_type(float v_in1, float v_in2, float v_out) { \
LOG(INFO) << "Test " << #op_type << " on GPU!"; \
half *in1, *in2; \
half *d_in1, *d_in2; \
int size = sizeof(half); \
hipMalloc(reinterpret_cast<void **>(&d_in1), size); \
hipMalloc(reinterpret_cast<void **>(&d_in2), size); \
in1 = reinterpret_cast<half *>(malloc(size)); \
in2 = reinterpret_cast<half *>(malloc(size)); \
in1[0] = float16(v_in1).to_half(); \
in2[0] = float16(v_in2).to_half(); \
hipMemcpy(d_in1, in1, size, hipMemcpyHostToDevice); \
hipMemcpy(d_in2, in2, size, hipMemcpyHostToDevice); \
hipLaunchKernelGGL(op_type, dim3(1), dim3(1), 0, 0, d_in1, d_in2); \
hipMemcpy(in1, d_in1, size, hipMemcpyDeviceToHost); \
EXPECT_EQ(static_cast<float>(float16(in1[0])), v_out); \
free(in1); \
free(in2); \
hipFree(d_in1); \
hipFree(d_in2); \
}
#define COMPARISON_KERNEL_LAUNCH(op_type) \
void Test##op_type(float v_in1, float v_in2, bool v_out) { \
LOG(INFO) << "Test " << #op_type << " on GPU!"; \
half *in1, *in2; \
half *d_in1, *d_in2; \
bool *out, *d_out; \
int size = sizeof(half); \
hipMalloc(reinterpret_cast<void **>(&d_in1), size); \
hipMalloc(reinterpret_cast<void **>(&d_in2), size); \
hipMalloc(reinterpret_cast<void **>(&d_out), 1); \
in1 = reinterpret_cast<half *>(malloc(size)); \
in2 = reinterpret_cast<half *>(malloc(size)); \
out = reinterpret_cast<bool *>(malloc(1)); \
in1[0] = float16(v_in1).to_half(); \
in2[0] = float16(v_in2).to_half(); \
hipMemcpy(d_in1, in1, size, hipMemcpyHostToDevice); \
hipMemcpy(d_in2, in2, size, hipMemcpyHostToDevice); \
hipLaunchKernelGGL(op_type, dim3(1), dim3(1), 0, 0, d_in1, d_in2, d_out); \
hipMemcpy(out, d_out, 1, hipMemcpyDeviceToHost); \
EXPECT_EQ(out[0], v_out); \
free(in1); \
free(in2); \
free(out); \
hipFree(d_in1); \
hipFree(d_in2); \
hipFree(d_out); \
}
#else
#define ARITHMETIC_KERNEL_LAUNCH(op_type) \
void Test##op_type(float v_in1, float v_in2, float v_out) { \
LOG(INFO) << "Test " << #op_type << " on GPU!"; \
half *in1, *in2, *out; \
half *d_in1, *d_in2, *d_out; \
int size = sizeof(half); \
cudaMalloc(reinterpret_cast<void **>(&d_in1), size); \
cudaMalloc(reinterpret_cast<void **>(&d_in2), size); \
cudaMalloc(reinterpret_cast<void **>(&d_out), size); \
in1 = reinterpret_cast<half *>(malloc(size)); \
in2 = reinterpret_cast<half *>(malloc(size)); \
out = reinterpret_cast<half *>(malloc(size)); \
in1[0] = float16(v_in1).to_half(); \
in2[0] = float16(v_in2).to_half(); \
cudaMemcpy(d_in1, in1, size, cudaMemcpyHostToDevice); \
cudaMemcpy(d_in2, in2, size, cudaMemcpyHostToDevice); \
op_type<<<1, 1>>>(d_in1, d_in2, d_out); \
cudaMemcpy(out, d_out, size, cudaMemcpyDeviceToHost); \
EXPECT_EQ(static_cast<float>(float16(out[0])), v_out); \
free(in1); \
free(in2); \
free(out); \
cudaFree(d_in1); \
cudaFree(d_in2); \
cudaFree(d_out); \
}
#define COMPOUND_KERNEL_LAUNCH(op_type) \
void Test##op_type(float v_in1, float v_in2, float v_out) { \
LOG(INFO) << "Test " << #op_type << " on GPU!"; \
half *in1, *in2; \
half *d_in1, *d_in2; \
int size = sizeof(half); \
cudaMalloc(reinterpret_cast<void **>(&d_in1), size); \
cudaMalloc(reinterpret_cast<void **>(&d_in2), size); \
in1 = reinterpret_cast<half *>(malloc(size)); \
in2 = reinterpret_cast<half *>(malloc(size)); \
in1[0] = float16(v_in1).to_half(); \
in2[0] = float16(v_in2).to_half(); \
cudaMemcpy(d_in1, in1, size, cudaMemcpyHostToDevice); \
cudaMemcpy(d_in2, in2, size, cudaMemcpyHostToDevice); \
op_type<<<1, 1>>>(d_in1, d_in2); \
cudaMemcpy(in1, d_in1, size, cudaMemcpyDeviceToHost); \
EXPECT_EQ(static_cast<float>(float16(in1[0])), v_out); \
free(in1); \
free(in2); \
cudaFree(d_in1); \
cudaFree(d_in2); \
}
#define COMPARISON_KERNEL_LAUNCH(op_type) \
void Test##op_type(float v_in1, float v_in2, bool v_out) { \
LOG(INFO) << "Test " << #op_type << " on GPU!"; \
half *in1, *in2; \
half *d_in1, *d_in2; \
bool *out, *d_out; \
int size = sizeof(half); \
cudaMalloc(reinterpret_cast<void **>(&d_in1), size); \
cudaMalloc(reinterpret_cast<void **>(&d_in2), size); \
cudaMalloc(reinterpret_cast<void **>(&d_out), 1); \
in1 = reinterpret_cast<half *>(malloc(size)); \
in2 = reinterpret_cast<half *>(malloc(size)); \
out = reinterpret_cast<bool *>(malloc(1)); \
in1[0] = float16(v_in1).to_half(); \
in2[0] = float16(v_in2).to_half(); \
cudaMemcpy(d_in1, in1, size, cudaMemcpyHostToDevice); \
cudaMemcpy(d_in2, in2, size, cudaMemcpyHostToDevice); \
op_type<<<1, 1>>>(d_in1, d_in2, d_out); \
cudaMemcpy(out, d_out, 1, cudaMemcpyDeviceToHost); \
EXPECT_EQ(out[0], v_out); \
free(in1); \
free(in2); \
free(out); \
cudaFree(d_in1); \
cudaFree(d_in2); \
cudaFree(d_out); \
}
#endif
namespace paddle {
namespace platform {
using float16 = phi::dtype::float16;
using namespace phi::dtype; // NOLINT
#if defined(PADDLE_WITH_HIP)
ARITHMETIC_KERNEL(Add, +)
ARITHMETIC_KERNEL(Sub, -)
ARITHMETIC_KERNEL(Mul, *)
ARITHMETIC_KERNEL(Div, /)
ARITHMETIC_KERNEL_LAUNCH(Add)
ARITHMETIC_KERNEL_LAUNCH(Sub)
ARITHMETIC_KERNEL_LAUNCH(Mul)
ARITHMETIC_KERNEL_LAUNCH(Div)
// Negative sign kernel
__global__ void Neg(half *in) { in[0] = -in[0]; }
void TestNeg(float v_in, float v_out) {
LOG(INFO) << "Test Neg on GPU!";
half *in, *d_in;
int size = sizeof(half);
#ifdef PADDLE_WITH_HIP
hipMalloc(reinterpret_cast<void **>(&d_in), size);
#else
cudaMalloc(reinterpret_cast<void **>(&d_in), size);
#endif
in = reinterpret_cast<half *>(malloc(size));
in[0] = float16(v_in).to_half();
#ifdef PADDLE_WITH_HIP
hipMemcpy(d_in, in, size, hipMemcpyHostToDevice);
#else
cudaMemcpy(d_in, in, size, cudaMemcpyHostToDevice);
#endif
Neg<<<1, 1>>>(d_in);
#ifdef PADDLE_WITH_HIP
hipMemcpy(in, d_in, size, hipMemcpyDeviceToHost);
#else
cudaMemcpy(in, d_in, size, cudaMemcpyDeviceToHost);
#endif
EXPECT_EQ(static_cast<float>(float16(in[0])), v_out);
free(in);
#ifdef PADDLE_WITH_HIP
hipFree(d_in);
#else
cudaFree(d_in);
#endif
}
COMPOUND_KERNEL(AddAssign, +=)
COMPOUND_KERNEL(SubAssign, -=)
COMPOUND_KERNEL(MulAssign, *=)
COMPOUND_KERNEL(DivAssign, /=)
COMPOUND_KERNEL_LAUNCH(AddAssign)
COMPOUND_KERNEL_LAUNCH(SubAssign)
COMPOUND_KERNEL_LAUNCH(MulAssign)
COMPOUND_KERNEL_LAUNCH(DivAssign)
COMPARISON_KERNEL(Equal, ==)
COMPARISON_KERNEL(NotEqual, !=)
COMPARISON_KERNEL(Less, <)
COMPARISON_KERNEL(LessEqual, <=)
COMPARISON_KERNEL(Greater, >)
COMPARISON_KERNEL(GreaterEqual, >=)
COMPARISON_KERNEL_LAUNCH(Equal)
COMPARISON_KERNEL_LAUNCH(NotEqual)
COMPARISON_KERNEL_LAUNCH(Less)
COMPARISON_KERNEL_LAUNCH(LessEqual)
COMPARISON_KERNEL_LAUNCH(Greater)
COMPARISON_KERNEL_LAUNCH(GreaterEqual)
TEST(float16, arithmetic_on_gpu) {
TestAdd(1, 2, 3);
TestSub(2, 1, 1);
TestMul(2, 3, 6);
TestDiv(6, 2, 3);
TestNeg(1, -1);
}
TEST(float16, compound_on_gpu) {
TestAddAssign(1, 2, 3);
TestSubAssign(2, 1, 1);
TestMulAssign(2, 3, 6);
TestDivAssign(6, 2, 3);
}
TEST(float16, comparison_on_gpu) {
TestEqual(1, 1, true);
TestEqual(1, 2, false);
TestNotEqual(2, 3, true);
TestNotEqual(2, 2, false);
TestLess(3, 4, true);
TestLess(3, 3, false);
TestLessEqual(3, 3, true);
TestLessEqual(3, 2, false);
TestGreater(4, 3, true);
TestGreater(4, 4, false);
TestGreaterEqual(4, 4, true);
TestGreaterEqual(4, 5, false);
}
#endif // CUDA_VERSION
TEST(float16, conversion_on_gpu) {
// Explicit conversion to and from cuda half
EXPECT_EQ(float16(float16(1.0f).to_half()).x, 0x3c00);
EXPECT_EQ(float16(float16(0.5f).to_half()).x, 0x3800);
EXPECT_EQ(float16(float16(0.33333f).to_half()).x, 0x3555);
EXPECT_EQ(float16(float16(0.0f).to_half()).x, 0x0000);
EXPECT_EQ(float16(float16(-0.0f).to_half()).x, 0x8000);
EXPECT_EQ(float16(float16(65504.0f).to_half()).x, 0x7bff);
EXPECT_EQ(float16(float16(65536.0f).to_half()).x, 0x7c00);
// Assignment operator
float16 v_assign;
v_assign = float16(1.0f).to_half();
EXPECT_EQ(v_assign.x, 0x3c00);
}
TEST(float16, dense_tensor_on_gpu) {
phi::DenseTensor src_tensor;
phi::DenseTensor gpu_tensor;
phi::DenseTensor dst_tensor;
float16 *src_ptr =
src_tensor.mutable_data<float16>(common::make_ddim({2, 2}), CPUPlace());
float16 arr[4] = {
float16(1.0f), float16(0.5f), float16(0.33333f), float16(0.0f)};
memcpy(src_ptr, arr, 4 * sizeof(float16));
// CPU DenseTensor to GPU DenseTensor
phi::GPUPlace gpu_place(0);
phi::GPUContext gpu_ctx(gpu_place);
gpu_ctx.SetAllocator(paddle::memory::allocation::AllocatorFacade::Instance()
.GetAllocator(gpu_place, gpu_ctx.stream())
.get());
gpu_ctx.PartialInitWithAllocator();
framework::TensorCopy(src_tensor, gpu_place, gpu_ctx, &gpu_tensor);
// GPU DenseTensor to CPU DenseTensor
framework::TensorCopy(gpu_tensor, CPUPlace(), gpu_ctx, &dst_tensor);
// Sync before comparing DenseTensors
gpu_ctx.Wait();
const float16 *dst_ptr = dst_tensor.data<float16>();
ASSERT_NE(src_ptr, dst_ptr);
for (size_t i = 0; i < 4; ++i) {
EXPECT_EQ(src_ptr[i].x, dst_ptr[i].x);
}
}
template <typename T>
struct Functor {
bool operator()(const T &val) {
return std::type_index(typeid(T)) ==
std::type_index(typeid(phi::dtype::float16));
}
};
TEST(float16, typeid) {
// the framework heavily used typeid hash
Functor<float16> functor;
float16 a = float16(.0f);
Functor<int> functor2;
int b(0);
// compile time assert
PADDLE_ENFORCE_EQ(
functor(a),
true,
common::errors::Unavailable("The float16 support in GPU failed."));
PADDLE_ENFORCE_EQ(
functor2(b),
false,
common::errors::Unavailable("The float16 support in GPU failed."));
}
// GPU test
TEST(float16, isinf) {
float16 a;
a.x = 0x7c00;
float16 b = float16(INFINITY);
// underflow to 0
float16 native_a(5e-40f);
EXPECT_EQ(std::isinf(a), true);
EXPECT_EQ(std::isinf(b), true);
#ifndef _WIN32
// overflow to inf
float16 native_b(5e40f);
EXPECT_EQ(std::isinf(native_b), true);
#endif
EXPECT_EQ(native_a, float16(0));
}
TEST(float16, isnan) {
float16 a;
a.x = 0x7fff;
float16 b = float16(NAN);
float16 c = float16(5e40);
// inf * +-0 will get a nan
float16 d = c * float16(0);
EXPECT_EQ(std::isnan(a), true);
EXPECT_EQ(std::isnan(b), true);
EXPECT_EQ(std::isnan(d), true);
}
TEST(float16, cast) {
float16 a;
a.x = 0x0070;
auto b = a;
{
// change semantic, keep the same value
float16 c = reinterpret_cast<float16 &>(reinterpret_cast<unsigned &>(b));
EXPECT_EQ(b, c);
}
{
// use uint32 low 16 bit store float16
uint32_t c = reinterpret_cast<uint32_t &>(b);
float16 d;
d.x = c;
EXPECT_EQ(b, d);
}
}
} // namespace platform
} // namespace paddle
+29
View File
@@ -0,0 +1,29 @@
/* 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. */
#include <gtest/gtest.h>
#include "paddle/extension.h"
#include "paddle/phi/backends/context_pool.h"
#include "paddle/phi/common/memory_utils.h"
TEST(InitPhi, InitPhi) {
phi::MemoryUtils::Instance().CheckMemoryMethod();
phi::MemoryUtils::Instance().InitDevices();
ASSERT_EQ(phi::DeviceContextPool::IsInitialized(), true);
}
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
+60
View File
@@ -0,0 +1,60 @@
/* Copyright (c) 2016 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. */
#include "paddle/fluid/platform/init.h"
#include "gtest/gtest.h"
#include "paddle/phi/core/platform/device_context.h"
TEST(InitDevices, CPU) {
using paddle::framework::InitDevices;
using phi::DeviceContextPool;
#if !defined(PADDLE_WITH_CUDA) && !defined(PADDLE_WITH_XPU) && \
!defined(PADDLE_WITH_HIP)
InitDevices();
DeviceContextPool& pool = DeviceContextPool::Instance();
ASSERT_EQ(pool.Size(), 1U);
#endif
}
TEST(InitDevices, CUDA) {
using paddle::framework::InitDevices;
using phi::DeviceContextPool;
#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP)
int count = paddle::platform::GetGPUDeviceCount();
InitDevices();
DeviceContextPool& pool = DeviceContextPool::Instance();
ASSERT_EQ(pool.Size(), 2U + static_cast<unsigned>(count));
#endif
}
TEST(InitDevices, XPU) {
using paddle::framework::InitDevices;
using phi::DeviceContextPool;
#ifdef PADDLE_WITH_XPU
int count = paddle::platform::GetXPUDeviceCount();
InitDevices();
DeviceContextPool& pool = DeviceContextPool::Instance();
ASSERT_EQ(pool.Size(), 2U + static_cast<unsigned>(count));
#endif
}
#ifndef _WIN32
TEST(SignalHandle, SignalHandle) {
std::string msg = "Signal raises";
paddle::framework::SignalHandle(msg.c_str(), static_cast<int>(msg.size()));
}
#endif
@@ -0,0 +1,23 @@
// Copyright (c) 2018 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.
#include "paddle/fluid/platform/densetensor_printer.h"
#include "gtest/gtest.h"
#include "paddle/fluid/framework/scope.h"
TEST(DenseTensorPrinter, PrintVar) {
paddle::framework::Scope scope;
std::stringstream ss;
paddle::platform::PrintVar(&scope, "NotAVar", "We don't have var", &ss);
}
+41
View File
@@ -0,0 +1,41 @@
// Copyright (c) 2018 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.
#include "paddle/phi/core/os_info.h"
#include <thread>
#include "gtest/gtest.h"
TEST(ThreadInfo, TestThreadIdUtils) {
using phi::GetAllThreadIds;
using phi::GetCurrentThreadId;
using phi::GetCurrentThreadStdId;
EXPECT_EQ(std::hash<std::thread::id>()(std::this_thread::get_id()),
GetCurrentThreadId().std_tid);
auto ids = GetAllThreadIds();
EXPECT_TRUE(ids.find(GetCurrentThreadStdId()) != ids.end());
}
TEST(ThreadInfo, TestThreadNameUtils) {
using phi::GetAllThreadNames;
using phi::GetCurrentThreadName;
using phi::GetCurrentThreadStdId;
using phi::SetCurrentThreadName;
SetCurrentThreadName("MainThread");
EXPECT_FALSE(SetCurrentThreadName("MainThread"));
auto names = GetAllThreadNames();
EXPECT_TRUE(names.find(GetCurrentThreadStdId()) != names.end());
EXPECT_EQ("MainThread", names[GetCurrentThreadStdId()]);
EXPECT_EQ("MainThread", GetCurrentThreadName());
}
+57
View File
@@ -0,0 +1,57 @@
// Copyright (c) 2018 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.
#include "paddle/phi/common/place.h"
#include "gtest/gtest.h"
TEST(Place, Equality) {
phi::CPUPlace cpu;
phi::GPUPlace g0(0), g1(1), gg0(0);
phi::XPUPlace x0(0), x1(1), xx0(0);
EXPECT_EQ(cpu, cpu);
EXPECT_EQ(g0, g0);
EXPECT_EQ(g1, g1);
EXPECT_EQ(g0, gg0);
EXPECT_EQ(x0, x0);
EXPECT_EQ(x1, x1);
EXPECT_EQ(x0, xx0);
EXPECT_NE(g0, g1);
EXPECT_NE(x0, x1);
EXPECT_TRUE(phi::places_are_same_class(g0, gg0));
EXPECT_TRUE(phi::places_are_same_class(x0, xx0));
EXPECT_FALSE(phi::places_are_same_class(g0, cpu));
EXPECT_FALSE(phi::places_are_same_class(x0, cpu));
EXPECT_FALSE(phi::places_are_same_class(g0, x0));
}
TEST(Place, Print) {
{
std::stringstream ss;
ss << phi::XPUPlace(1);
EXPECT_EQ("Place(xpu:1)", ss.str());
}
{
std::stringstream ss;
ss << phi::GPUPlace(1);
EXPECT_EQ("Place(gpu:1)", ss.str());
}
{
std::stringstream ss;
ss << phi::CPUPlace();
EXPECT_EQ("Place(cpu)", ss.str());
}
}
@@ -0,0 +1,16 @@
cc_test(
test_event_node
SRCS test_event_node.cc
DEPS event_node profiler_logger)
cc_test(
test_extra_info
SRCS test_extra_info.cc
DEPS phi glog common)
cc_test(
test_serialization_logger
SRCS dump/test_serialization_logger.cc
DEPS event_bind)
cc_test(
new_profiler_test
SRCS profiler_test.cc
DEPS new_profiler)
@@ -0,0 +1,315 @@
// Copyright (c) 2021 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.
#include "gtest/gtest.h"
#include "paddle/fluid/framework/type_defs.h"
#include "paddle/fluid/platform/profiler/dump/deserialization_reader.h"
#include "paddle/fluid/platform/profiler/dump/serialization_logger.h"
#include "paddle/fluid/platform/profiler/event_node.h"
#include "paddle/fluid/platform/profiler/event_python.h"
using paddle::framework::AttributeMap;
using paddle::platform::DeserializationReader;
using paddle::platform::DeviceTraceEvent;
using paddle::platform::HostTraceEvent;
using paddle::platform::HostTraceEventNode;
using paddle::platform::KernelEventInfo;
using paddle::platform::MemcpyEventInfo;
using paddle::platform::MemsetEventInfo;
using paddle::platform::MemTraceEvent;
using paddle::platform::NodeTrees;
using paddle::platform::OperatorSupplementEvent;
using paddle::platform::RuntimeTraceEvent;
using paddle::platform::SerializationLogger;
using phi::TracerEventType;
using phi::TracerMemEventType;
TEST(SerializationLoggerTest, dump_case0) {
std::list<HostTraceEvent> host_events;
std::list<RuntimeTraceEvent> runtime_events;
std::list<DeviceTraceEvent> device_events;
std::list<MemTraceEvent> mem_events;
std::list<OperatorSupplementEvent> op_supplement_events;
host_events.emplace_back(std::string("dataloader#1"),
TracerEventType::Dataloader,
1000,
10000,
10,
10);
host_events.emplace_back(
std::string("op1"), TracerEventType::Operator, 11000, 20000, 10, 10);
host_events.emplace_back(
std::string("op2"), TracerEventType::Operator, 21000, 30000, 10, 10);
host_events.emplace_back(
std::string("op3"), TracerEventType::Operator, 31000, 40000, 10, 11);
mem_events.emplace_back(11500,
0x1000,
TracerMemEventType::Allocate,
10,
10,
50,
"GPU:0",
50,
50,
100,
100);
mem_events.emplace_back(11900,
0x1000,
TracerMemEventType::Free,
10,
10,
-50,
"GPU:0",
0,
50,
100,
100);
std::map<std::string, std::vector<std::vector<int64_t>>> input_shapes;
std::map<std::string, std::vector<std::string>> dtypes;
input_shapes[std::string("X")].push_back(std::vector<int64_t>{1, 2, 3});
input_shapes[std::string("X")].push_back(std::vector<int64_t>{4, 5, 6, 7});
dtypes[std::string("X")].emplace_back("int8");
dtypes[std::string("X")].emplace_back("float32");
AttributeMap attrs;
op_supplement_events.emplace_back(
11600, "op1", input_shapes, dtypes, "op1()", attrs, 0, 10, 10);
runtime_events.emplace_back(
std::string("cudalaunch1"), 15000, 17000, 10, 10, 1, 0);
runtime_events.emplace_back(
std::string("cudalaunch2"), 25000, 35000, 10, 10, 2, 0);
runtime_events.emplace_back(
std::string("cudalaunch3"), 33000, 37000, 10, 11, 3, 0);
runtime_events.emplace_back(
std::string("cudaMemcpy1"), 18000, 19000, 10, 10, 4, 0);
runtime_events.emplace_back(
std::string("cudaMemset1"), 38000, 39000, 10, 11, 5, 0);
device_events.emplace_back(std::string("kernel1"),
TracerEventType::Kernel,
40000,
55000,
0,
10,
10,
1,
KernelEventInfo());
device_events.emplace_back(std::string("kernel2"),
TracerEventType::Kernel,
70000,
95000,
0,
10,
10,
2,
KernelEventInfo());
device_events.emplace_back(std::string("kernel3"),
TracerEventType::Kernel,
60000,
65000,
0,
10,
11,
3,
KernelEventInfo());
device_events.emplace_back(std::string("memcpy1"),
TracerEventType::Memcpy,
56000,
59000,
0,
10,
10,
4,
MemcpyEventInfo());
device_events.emplace_back(std::string("memset1"),
TracerEventType::Memset,
66000,
69000,
0,
10,
11,
5,
MemsetEventInfo());
SerializationLogger logger("test_serialization_logger_case0.pb");
logger.LogMetaInfo(std::string("1.0.2"), 0);
NodeTrees tree(host_events,
runtime_events,
device_events,
mem_events,
op_supplement_events);
std::map<uint64_t, std::vector<HostTraceEventNode*>> nodes =
tree.Traverse(true);
EXPECT_EQ(nodes[10].size(), 4u);
EXPECT_EQ(nodes[11].size(), 2u);
std::vector<HostTraceEventNode*> thread1_nodes = nodes[10];
std::vector<HostTraceEventNode*> thread2_nodes = nodes[11];
for (auto& thread1_node : thread1_nodes) {
if (thread1_node->Name() == "root node") {
EXPECT_EQ(thread1_node->GetChildren().size(), 3u);
}
if (thread1_node->Name() == "op1") {
EXPECT_EQ(thread1_node->GetChildren().size(), 0u);
EXPECT_EQ(thread1_node->GetRuntimeTraceEventNodes().size(), 2u);
EXPECT_EQ(thread1_node->GetMemTraceEventNodes().size(), 2u);
EXPECT_NE(thread1_node->GetOperatorSupplementEventNode(), nullptr);
}
}
for (auto& thread2_node : thread2_nodes) {
if (thread2_node->Name() == "op3") {
EXPECT_EQ(thread2_node->GetChildren().size(), 0u);
EXPECT_EQ(thread2_node->GetRuntimeTraceEventNodes().size(), 2u);
}
}
tree.LogMe(&logger);
logger.LogExtraInfo(std::unordered_map<std::string, std::string>());
}
TEST(SerializationLoggerTest, dump_case1) {
std::list<HostTraceEvent> host_events;
std::list<RuntimeTraceEvent> runtime_events;
std::list<DeviceTraceEvent> device_events;
std::list<MemTraceEvent> mem_events;
std::list<OperatorSupplementEvent> op_supplement_events;
runtime_events.emplace_back(
std::string("cudalaunch1"), 15000, 17000, 10, 10, 1, 0);
runtime_events.emplace_back(
std::string("cudalaunch2"), 25000, 35000, 10, 10, 2, 0);
runtime_events.emplace_back(
std::string("cudalaunch3"), 33000, 37000, 10, 11, 3, 0);
runtime_events.emplace_back(
std::string("cudaMemcpy1"), 18000, 19000, 10, 10, 4, 0);
runtime_events.emplace_back(
std::string("cudaMemset1"), 38000, 39000, 10, 11, 5, 0);
device_events.emplace_back(std::string("kernel1"),
TracerEventType::Kernel,
40000,
55000,
0,
10,
10,
1,
KernelEventInfo());
device_events.emplace_back(std::string("kernel2"),
TracerEventType::Kernel,
70000,
95000,
0,
10,
10,
2,
KernelEventInfo());
device_events.emplace_back(std::string("kernel3"),
TracerEventType::Kernel,
60000,
65000,
0,
10,
11,
3,
KernelEventInfo());
device_events.emplace_back(std::string("memcpy1"),
TracerEventType::Memcpy,
56000,
59000,
0,
10,
10,
4,
MemcpyEventInfo());
device_events.emplace_back(std::string("memset1"),
TracerEventType::Memset,
66000,
69000,
0,
10,
11,
5,
MemsetEventInfo());
SerializationLogger logger("test_serialization_logger_case1.pb");
logger.LogMetaInfo(std::string("1.0.2"), 0);
NodeTrees tree(host_events,
runtime_events,
device_events,
mem_events,
op_supplement_events);
std::map<uint64_t, std::vector<HostTraceEventNode*>> nodes =
tree.Traverse(true);
EXPECT_EQ(nodes[10].size(), 1u);
EXPECT_EQ(nodes[11].size(), 1u);
std::vector<HostTraceEventNode*> thread1_nodes = nodes[10];
std::vector<HostTraceEventNode*> thread2_nodes = nodes[11];
for (auto& thread1_node : thread1_nodes) {
if (thread1_node->Name() == "root node") {
EXPECT_EQ(thread1_node->GetRuntimeTraceEventNodes().size(), 3u);
}
}
for (auto& thread2_node : thread2_nodes) {
if (thread2_node->Name() == "root node") {
EXPECT_EQ(thread2_node->GetChildren().size(), 0u);
EXPECT_EQ(thread2_node->GetRuntimeTraceEventNodes().size(), 2u);
}
}
tree.LogMe(&logger);
logger.LogExtraInfo(std::unordered_map<std::string, std::string>());
}
TEST(DeserializationReaderTest, restore_case0) {
DeserializationReader reader("test_serialization_logger_case0.pb");
auto profiler_result = reader.Parse();
auto tree = profiler_result->GetNodeTrees();
std::map<uint64_t, std::vector<HostTraceEventNode*>> nodes =
tree->Traverse(true);
EXPECT_EQ(nodes[10].size(), 4u);
EXPECT_EQ(nodes[11].size(), 2u);
std::vector<HostTraceEventNode*> thread1_nodes = nodes[10];
std::vector<HostTraceEventNode*> thread2_nodes = nodes[11];
for (auto& thread1_node : thread1_nodes) {
if (thread1_node->Name() == "root node") {
EXPECT_EQ(thread1_node->GetChildren().size(), 3u);
}
if (thread1_node->Name() == "op1") {
EXPECT_EQ(thread1_node->GetChildren().size(), 0u);
EXPECT_EQ(thread1_node->GetRuntimeTraceEventNodes().size(), 2u);
EXPECT_EQ(thread1_node->GetMemTraceEventNodes().size(), 2u);
EXPECT_NE(thread1_node->GetOperatorSupplementEventNode(), nullptr);
}
}
for (auto& thread2_node : thread2_nodes) {
if (thread2_node->Name() == "op3") {
EXPECT_EQ(thread2_node->GetChildren().size(), 0u);
EXPECT_EQ(thread2_node->GetRuntimeTraceEventNodes().size(), 2u);
}
}
}
TEST(DeserializationReaderTest, restore_case1) {
DeserializationReader reader("test_serialization_logger_case1.pb");
auto profiler_result = reader.Parse();
auto tree = profiler_result->GetNodeTrees();
std::map<uint64_t, std::vector<HostTraceEventNode*>> nodes =
tree->Traverse(true);
EXPECT_EQ(nodes[10].size(), 1u);
EXPECT_EQ(nodes[11].size(), 1u);
std::vector<HostTraceEventNode*> thread1_nodes = nodes[10];
std::vector<HostTraceEventNode*> thread2_nodes = nodes[11];
for (auto& thread1_node : thread1_nodes) {
if (thread1_node->Name() == "root node") {
EXPECT_EQ(thread1_node->GetRuntimeTraceEventNodes().size(), 3u);
}
}
for (auto& thread2_node : thread2_nodes) {
if (thread2_node->Name() == "root node") {
EXPECT_EQ(thread2_node->GetChildren().size(), 0u);
EXPECT_EQ(thread2_node->GetRuntimeTraceEventNodes().size(), 2u);
}
}
}
@@ -0,0 +1,145 @@
// Copyright (c) 2022 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.
#include <set>
#include <string>
#include "glog/logging.h"
#include "gtest/gtest.h"
#ifdef PADDLE_WITH_CUDA
#include <cuda.h>
#endif
#ifdef PADDLE_WITH_HIP
#include <hip/hip_runtime.h>
#endif
#include "paddle/fluid/platform/profiler/event_python.h"
#include "paddle/fluid/platform/profiler/profiler.h"
#include "paddle/phi/common/place.h"
#include "paddle/phi/core/platform/profiler.h"
#include "paddle/phi/core/platform/profiler/event_tracing.h"
TEST(ProfilerTest, TestHostTracer) {
using paddle::platform::Profiler;
using paddle::platform::ProfilerOptions;
using paddle::platform::ProfilerResult;
using paddle::platform::RecordInstantEvent;
using phi::TracerEventType;
ProfilerOptions options;
options.trace_level = 2;
options.trace_switch = 3;
auto profiler = Profiler::Create(options);
EXPECT_TRUE(profiler);
profiler->Prepare();
profiler->Start();
{
RecordInstantEvent(
"TestTraceLevel_record1", TracerEventType::UserDefined, 2);
RecordInstantEvent(
"TestTraceLevel_record2", TracerEventType::UserDefined, 3);
}
auto profiler_result = profiler->Stop();
auto nodetree = profiler_result->GetNodeTrees();
std::set<std::string> host_events;
for (const auto& pair : nodetree->Traverse(true)) {
for (const auto evt : pair.second) {
host_events.insert(evt->Name());
}
}
EXPECT_EQ(host_events.count("TestTraceLevel_record1"), 1u);
EXPECT_EQ(host_events.count("TestTraceLevel_record2"), 0u);
}
TEST(ProfilerTest, TestCudaTracer) {
using paddle::platform::Profiler;
using paddle::platform::ProfilerOptions;
using paddle::platform::ProfilerResult;
ProfilerOptions options;
options.trace_level = 0;
options.trace_switch = 3;
auto profiler = Profiler::Create(options);
EXPECT_TRUE(profiler);
profiler->Prepare();
profiler->Start();
#ifdef PADDLE_WITH_CUDA
cudaStream_t stream;
cudaStreamCreate(&stream);
cudaStreamSynchronize(stream);
#endif
#ifdef PADDLE_WITH_HIP
hipStream_t stream;
hipStreamCreate(&stream);
hipStreamSynchronize(stream);
#endif
auto profiler_result = profiler->Stop();
auto nodetree = profiler_result->GetNodeTrees();
std::vector<std::string> runtime_events;
for (const auto& pair : nodetree->Traverse(true)) {
for (const auto host_node : pair.second) {
for (auto runtime_node : host_node->GetRuntimeTraceEventNodes()) {
runtime_events.push_back(runtime_node->Name());
}
}
}
#ifdef PADDLE_WITH_CUPTI
#ifndef PADDLE_WITH_XPU
EXPECT_GT(runtime_events.size(), 0u);
#endif
#endif
}
TEST(ProfilerTest, TestHostTracerForMem) {
using paddle::platform::EnableHostEventRecorder;
using paddle::platform::MemTraceEventNode;
using paddle::platform::Profiler;
using paddle::platform::ProfilerOptions;
using paddle::platform::ProfilerResult;
using paddle::platform::RecordInstantEvent;
using paddle::platform::RecordMemEvent;
using phi::CPUPlace;
using phi::RecordEvent;
using phi::TracerEventType;
using phi::TracerMemEventType;
ProfilerOptions options;
options.trace_level = 1;
options.trace_switch = 3;
auto profiler = Profiler::Create(options);
EXPECT_TRUE(profiler);
EnableHostEventRecorder();
profiler->Prepare();
profiler->Start();
{
RecordEvent event1(
"TestTracerForMem_phase1", TracerEventType::UserDefined, 1);
RecordMemEvent(reinterpret_cast<void*>(0),
CPUPlace(),
1024,
TracerMemEventType::Allocate);
RecordMemEvent(
reinterpret_cast<void*>(0), CPUPlace(), 1024, TracerMemEventType::Free);
}
{
RecordEvent event2(
"TestTracerForMem_phase2", TracerEventType::UserDefined, 1);
RecordMemEvent(reinterpret_cast<void*>(1024),
CPUPlace(),
1024,
TracerMemEventType::Allocate);
RecordMemEvent(reinterpret_cast<void*>(1024),
CPUPlace(),
1024,
TracerMemEventType::Free);
}
auto profiler_result = profiler->Stop();
auto nodetree = profiler_result->GetNodeTrees();
}
@@ -0,0 +1,390 @@
// Copyright (c) 2022 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.
#include "gtest/gtest.h"
#include "paddle/fluid/framework/type_defs.h"
#include "paddle/fluid/platform/profiler/chrometracing_logger.h"
#include "paddle/fluid/platform/profiler/event_node.h"
using paddle::framework::AttributeMap;
using paddle::platform::ChromeTracingLogger;
using paddle::platform::CudaRuntimeTraceEventNode;
using paddle::platform::DeviceTraceEvent;
using paddle::platform::DeviceTraceEventNode;
using paddle::platform::HostTraceEvent;
using paddle::platform::HostTraceEventNode;
using paddle::platform::KernelEventInfo;
using paddle::platform::MemcpyEventInfo;
using paddle::platform::MemsetEventInfo;
using paddle::platform::MemTraceEvent;
using paddle::platform::MemTraceEventNode;
using paddle::platform::NodeTrees;
using paddle::platform::OperatorSupplementEvent;
using paddle::platform::OperatorSupplementEventNode;
using paddle::platform::RuntimeTraceEvent;
using phi::TracerEventType;
using phi::TracerMemEventType;
TEST(NodeTreesTest, LogMe_case0) {
std::list<HostTraceEvent> host_events;
std::list<RuntimeTraceEvent> runtime_events;
std::list<DeviceTraceEvent> device_events;
std::list<MemTraceEvent> mem_events;
std::list<OperatorSupplementEvent> op_supplement_events;
host_events.emplace_back(std::string("dataloader#1"),
TracerEventType::Dataloader,
1000,
10000,
10,
10);
host_events.emplace_back(
std::string("op1"), TracerEventType::Operator, 11000, 20000, 10, 10);
host_events.emplace_back(
std::string("op2"), TracerEventType::Operator, 21000, 30000, 10, 10);
host_events.emplace_back(
std::string("op3"), TracerEventType::Operator, 31000, 40000, 10, 11);
mem_events.emplace_back(11500,
0x1000,
TracerMemEventType::Allocate,
10,
10,
50,
"GPU:0",
50,
50,
100,
100);
mem_events.emplace_back(11900,
0x1000,
TracerMemEventType::Free,
10,
10,
-50,
"GPU:0",
0,
50,
100,
100);
std::map<std::string, std::vector<std::vector<int64_t>>> input_shapes;
std::map<std::string, std::vector<std::string>> dtypes;
input_shapes[std::string("X")].push_back(std::vector<int64_t>{1, 2, 3});
input_shapes[std::string("X")].push_back(std::vector<int64_t>{4, 5, 6, 7});
dtypes[std::string("X")].emplace_back("int8");
dtypes[std::string("X")].emplace_back("float32");
AttributeMap attrs;
op_supplement_events.emplace_back(
11600, "op1", input_shapes, dtypes, "op1()", attrs, 0, 10, 10);
runtime_events.emplace_back(
std::string("cudalaunch1"), 15000, 17000, 10, 10, 1, 0);
runtime_events.emplace_back(
std::string("cudalaunch2"), 25000, 35000, 10, 10, 2, 0);
runtime_events.emplace_back(
std::string("cudalaunch3"), 33000, 37000, 10, 11, 3, 0);
runtime_events.emplace_back(
std::string("cudaMemcpy1"), 18000, 19000, 10, 10, 4, 0);
runtime_events.emplace_back(
std::string("cudaMemset1"), 38000, 39000, 10, 11, 5, 0);
device_events.emplace_back(std::string("kernel1"),
TracerEventType::Kernel,
40000,
55000,
0,
10,
10,
1,
KernelEventInfo());
device_events.emplace_back(std::string("kernel2"),
TracerEventType::Kernel,
70000,
95000,
0,
10,
10,
2,
KernelEventInfo());
device_events.emplace_back(std::string("kernel3"),
TracerEventType::Kernel,
60000,
65000,
0,
10,
11,
3,
KernelEventInfo());
device_events.emplace_back(std::string("memcpy1"),
TracerEventType::Memcpy,
56000,
59000,
0,
10,
10,
4,
MemcpyEventInfo());
device_events.emplace_back(std::string("memset1"),
TracerEventType::Memset,
66000,
69000,
0,
10,
11,
5,
MemsetEventInfo());
ChromeTracingLogger logger("test_nodetrees_logme_case0.json");
logger.LogMetaInfo(std::string("1.0.2"), 0);
NodeTrees tree(host_events,
runtime_events,
device_events,
mem_events,
op_supplement_events);
std::map<uint64_t, std::vector<HostTraceEventNode*>> nodes =
tree.Traverse(true);
EXPECT_EQ(nodes[10].size(), 4u);
EXPECT_EQ(nodes[11].size(), 2u);
std::vector<HostTraceEventNode*> thread1_nodes = nodes[10];
std::vector<HostTraceEventNode*> thread2_nodes = nodes[11];
for (auto& thread1_node : thread1_nodes) {
if (thread1_node->Name() == "root node") {
EXPECT_EQ(thread1_node->GetChildren().size(), 3u);
}
if (thread1_node->Name() == "op1") {
EXPECT_EQ(thread1_node->GetChildren().size(), 0u);
EXPECT_EQ(thread1_node->GetRuntimeTraceEventNodes().size(), 2u);
EXPECT_EQ(thread1_node->GetMemTraceEventNodes().size(), 2u);
EXPECT_NE(thread1_node->GetOperatorSupplementEventNode(), nullptr);
}
}
for (auto& thread2_node : thread2_nodes) {
if (thread2_node->Name() == "op3") {
EXPECT_EQ(thread2_node->GetChildren().size(), 0u);
EXPECT_EQ(thread2_node->GetRuntimeTraceEventNodes().size(), 2u);
}
}
tree.LogMe(&logger);
logger.LogExtraInfo(std::unordered_map<std::string, std::string>());
}
TEST(NodeTreesTest, LogMe_case1) {
std::list<HostTraceEvent> host_events;
std::list<RuntimeTraceEvent> runtime_events;
std::list<DeviceTraceEvent> device_events;
std::list<MemTraceEvent> mem_events;
std::list<OperatorSupplementEvent> op_supplement_events;
runtime_events.emplace_back(
std::string("cudalaunch1"), 15000, 17000, 10, 10, 1, 0);
runtime_events.emplace_back(
std::string("cudalaunch2"), 25000, 35000, 10, 10, 2, 0);
runtime_events.emplace_back(
std::string("cudalaunch3"), 33000, 37000, 10, 11, 3, 0);
runtime_events.emplace_back(
std::string("cudaMemcpy1"), 18000, 19000, 10, 10, 4, 0);
runtime_events.emplace_back(
std::string("cudaMemset1"), 38000, 39000, 10, 11, 5, 0);
device_events.emplace_back(std::string("kernel1"),
TracerEventType::Kernel,
40000,
55000,
0,
10,
10,
1,
KernelEventInfo());
device_events.emplace_back(std::string("kernel2"),
TracerEventType::Kernel,
70000,
95000,
0,
10,
10,
2,
KernelEventInfo());
device_events.emplace_back(std::string("kernel3"),
TracerEventType::Kernel,
60000,
65000,
0,
10,
11,
3,
KernelEventInfo());
device_events.emplace_back(std::string("memcpy1"),
TracerEventType::Memcpy,
56000,
59000,
0,
10,
10,
4,
MemcpyEventInfo());
device_events.emplace_back(std::string("memset1"),
TracerEventType::Memset,
66000,
69000,
0,
10,
11,
5,
MemsetEventInfo());
ChromeTracingLogger logger("test_nodetrees_logme_case1.json");
logger.LogMetaInfo(std::string("1.0.2"), 0);
NodeTrees tree(host_events,
runtime_events,
device_events,
mem_events,
op_supplement_events);
std::map<uint64_t, std::vector<HostTraceEventNode*>> nodes =
tree.Traverse(true);
EXPECT_EQ(nodes[10].size(), 1u);
EXPECT_EQ(nodes[11].size(), 1u);
std::vector<HostTraceEventNode*> thread1_nodes = nodes[10];
std::vector<HostTraceEventNode*> thread2_nodes = nodes[11];
for (auto& thread1_node : thread1_nodes) {
if (thread1_node->Name() == "root node") {
EXPECT_EQ(thread1_node->GetRuntimeTraceEventNodes().size(), 3u);
}
}
for (auto& thread2_node : thread2_nodes) {
if (thread2_node->Name() == "root node") {
EXPECT_EQ(thread2_node->GetChildren().size(), 0u);
EXPECT_EQ(thread2_node->GetRuntimeTraceEventNodes().size(), 2u);
}
}
tree.LogMe(&logger);
logger.LogExtraInfo(std::unordered_map<std::string, std::string>());
}
TEST(NodeTreesTest, HandleTrees_case0) {
std::list<HostTraceEvent> host_events;
std::list<RuntimeTraceEvent> runtime_events;
std::list<DeviceTraceEvent> device_events;
std::list<MemTraceEvent> mem_events;
std::list<OperatorSupplementEvent> op_supplement_events;
host_events.emplace_back(
std::string("op1"), TracerEventType::Operator, 10000, 100000, 10, 10);
host_events.emplace_back(
std::string("op2"), TracerEventType::Operator, 30000, 70000, 10, 10);
host_events.emplace_back(
std::string("op3"), TracerEventType::Operator, 2000, 120000, 10, 11);
mem_events.emplace_back(11500,
0x1000,
TracerMemEventType::Allocate,
10,
10,
50,
"GPU:0",
50,
50,
100,
100);
mem_events.emplace_back(11900,
0x1000,
TracerMemEventType::Free,
10,
10,
-50,
"GPU:0",
0,
50,
100,
100);
AttributeMap attrs;
op_supplement_events.emplace_back(
11600,
"op1",
std::map<std::string, std::vector<std::vector<int64_t>>>(),
std::map<std::string, std::vector<std::string>>(),
"op1()",
attrs,
0,
10,
10);
runtime_events.emplace_back(
std::string("cudalaunch1"), 15000, 25000, 10, 10, 1, 0);
runtime_events.emplace_back(
std::string("cudalaunch2"), 35000, 45000, 10, 10, 2, 0);
runtime_events.emplace_back(
std::string("cudalaunch3"), 10000, 55000, 10, 11, 3, 0);
device_events.emplace_back(std::string("kernel1"),
TracerEventType::Kernel,
40000,
55000,
0,
10,
10,
1,
KernelEventInfo());
device_events.emplace_back(std::string("kernel2"),
TracerEventType::Kernel,
70000,
95000,
0,
10,
10,
2,
KernelEventInfo());
device_events.emplace_back(std::string("kernel3"),
TracerEventType::Kernel,
60000,
75000,
0,
10,
11,
3,
KernelEventInfo());
ChromeTracingLogger logger("test_nodetrees_handletrees_case0.json");
logger.LogMetaInfo(std::string("1.0.2"), 0);
NodeTrees tree(host_events,
runtime_events,
device_events,
mem_events,
op_supplement_events);
std::map<uint64_t, std::vector<HostTraceEventNode*>> nodes =
tree.Traverse(true);
EXPECT_EQ(nodes[10].size(), 3u);
EXPECT_EQ(nodes[11].size(), 2u);
std::vector<HostTraceEventNode*> thread1_nodes = nodes[10];
std::vector<HostTraceEventNode*> thread2_nodes = nodes[11];
for (auto& thread1_node : thread1_nodes) {
if (thread1_node->Name() == "root node") {
EXPECT_EQ(thread1_node->GetChildren().size(), 1u);
}
if (thread1_node->Name() == "op1") {
EXPECT_EQ(thread1_node->GetChildren().size(), 1u);
EXPECT_EQ(thread1_node->GetRuntimeTraceEventNodes().size(), 1u);
}
}
for (auto& thread2_node : thread2_nodes) {
if (thread2_node->Name() == "op3") {
EXPECT_EQ(thread2_node->GetChildren().size(), 0u);
EXPECT_EQ(thread2_node->GetRuntimeTraceEventNodes().size(), 1u);
}
}
std::function<void(HostTraceEventNode*)> host_event_node_handle(
[&](HostTraceEventNode* a) { logger.LogHostTraceEventNode(*a); });
std::function<void(CudaRuntimeTraceEventNode*)> runtime_event_node_handle(
[&](CudaRuntimeTraceEventNode* a) {
logger.LogRuntimeTraceEventNode(*a);
});
std::function<void(DeviceTraceEventNode*)> device_event_node_handle(
[&](DeviceTraceEventNode* a) { logger.LogDeviceTraceEventNode(*a); });
std::function<void(MemTraceEventNode*)> mem_event_node_handle(
[&](MemTraceEventNode* a) { logger.LogMemTraceEventNode(*a); });
std::function<void(OperatorSupplementEventNode*)>
op_supplement_event_node_handle([&](OperatorSupplementEventNode* a) {});
tree.HandleTrees(host_event_node_handle,
runtime_event_node_handle,
device_event_node_handle,
mem_event_node_handle,
op_supplement_event_node_handle);
logger.LogExtraInfo(std::unordered_map<std::string, std::string>());
}
@@ -0,0 +1,31 @@
// Copyright (c) 2022 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.
#include "gtest/gtest.h"
#include "paddle/phi/core/platform/profiler/extra_info.h"
using paddle::platform::ExtraInfo;
TEST(ExtraInfoTest, case0) {
ExtraInfo instance;
instance.AddExtraInfo(std::string("info1"), std::string("%d"), 20);
instance.AddExtraInfo(std::string("info2"), std::string("%s"), "helloworld");
std::unordered_map<std::string, std::string> map = instance.GetExtraInfo();
EXPECT_EQ(map["info1"], "20");
EXPECT_EQ(map["info2"], "helloworld");
EXPECT_EQ(map.size(), 2u);
instance.Clear();
map = instance.GetExtraInfo();
EXPECT_EQ(map.size(), 0u);
}
+159
View File
@@ -0,0 +1,159 @@
/* Copyright (c) 2016 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. */
#include "paddle/phi/core/platform/profiler.h"
#include <string>
#include "glog/logging.h"
#include "gtest/gtest.h"
TEST(Event, CpuElapsedTime) {
using phi::Event;
using phi::EventType;
Event start_event(EventType::kPushRange, "test", 0);
int counter = 0;
while (counter != 1000) {
counter++;
}
#ifdef _WIN32
Sleep(1);
#endif
Event stop_event(EventType::kPopRange, "test", 0);
EXPECT_GT(start_event.CpuElapsedMs(stop_event), 0);
}
TEST(RecordEvent, RecordEvent) {
using paddle::platform::EventSortingKey;
using phi::Event;
using phi::EventRole;
using phi::EventType;
using phi::PopEvent;
using phi::ProfilerState;
using phi::PushEvent;
using phi::RecordEvent;
ProfilerState state = ProfilerState::kCPU;
paddle::platform::EnableProfiler(state);
/* Usage 1:
* PushEvent(evt_name);
* ...
* code to be analyzed
* ...
* PopEvent(evt_name);
*/
LOG(INFO) << "Usage 1: PushEvent & PopEvent";
for (int loop = 0; loop < 3; ++loop) {
for (int i = 1; i < 5; ++i) {
std::string name = "op_" + std::to_string(i);
PushEvent(name, EventRole::kOrdinary);
int counter = 1;
while (counter != i * 1000) counter++;
PopEvent(name, EventRole::kOrdinary);
}
}
/* Usage 2:
* {
* RecordEvent record_event(name);
* ...
* code to be analyzed
* ...
* }
*/
LOG(INFO) << "Usage 2: RecordEvent";
for (int i = 1; i < 5; ++i) {
std::string name = "evs_op_" + std::to_string(i);
RecordEvent record_event(name);
int counter = 1;
while (counter != i * 1000) counter++;
}
/* Usage 3
* {
* RecordEvent record_event(name1, dev_ctx);
* ...
* code to be analyzed
* ...
* {
* RecordEvent nested_record_event(name2, dev_ctx);
* ...
* code to be analyzed
* ...
* }
* }
*/
LOG(INFO) << "Usage 3: nested RecordEvent";
for (int i = 1; i < 5; ++i) {
std::string name = "ano_evs_op_" + std::to_string(i);
RecordEvent record_event(name);
int counter = 1;
while (counter != i * 100) counter++;
{
std::string nested_name = "nested_ano_evs_op_" + std::to_string(i);
RecordEvent nested_record_event(nested_name);
int nested_counter = 1;
while (nested_counter != i * 100) nested_counter++;
}
}
// Bad Usage:
PushEvent("event_without_pop", EventRole::kOrdinary);
PopEvent("event_without_push", EventRole::kOrdinary);
std::vector<std::vector<Event>> events = paddle::platform::GetAllEvents();
int cuda_startup_count = 0;
int start_profiler_count = 0;
for (auto& item : events) {
for (size_t j = 0; j < item.size(); ++j) {
if (item[j].name() == "_cuda_startup_") ++cuda_startup_count;
if (item[j].name() == "_start_profiler_") ++start_profiler_count;
if (item[j].name() == "push") {
EXPECT_EQ(item[j + 1].name(), "pop");
#if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP)
EXPECT_GT(item[j].CudaElapsedMs(item[j + 1]), 0);
#else
EXPECT_GT(item[j].CpuElapsedMs(item[j + 1]), 0);
#endif
}
}
}
EXPECT_EQ(cuda_startup_count % 5, 0);
EXPECT_EQ(start_profiler_count, 1);
// Will remove parsing-related code from test later
DisableProfiler(EventSortingKey::kTotal, "/tmp/profiler");
}
#ifdef PADDLE_WITH_CUDA
TEST(TMP, stream_wait) {
cudaStream_t stream;
cudaStreamCreate(&stream);
cudaStreamSynchronize(stream);
cudaStreamSynchronize(stream);
cudaStreamSynchronize(stream);
}
#endif
#ifdef PADDLE_WITH_HIP
TEST(TMP, stream_wait) {
hipStream_t stream;
hipStreamCreate(&stream);
hipStreamSynchronize(stream);
hipStreamSynchronize(stream);
hipStreamSynchronize(stream);
}
#endif
@@ -0,0 +1,96 @@
// Copyright (c) 2020 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.
#include "gtest/gtest.h"
#include "paddle/common/flags.h"
#include "paddle/phi/core/platform/cuda_device_guard.h"
#include "paddle/phi/core/platform/device/gpu/gpu_info.h"
COMMON_DECLARE_uint64(gpu_memory_limit_mb);
namespace paddle {
namespace platform {
static constexpr uint64_t GPU_MEMORY_LIMIT_MB = 500;
static constexpr int DEVICE_ID = 0;
TEST(test_record_malloc, test_limit_gpu_memory) {
FLAGS_gpu_memory_limit_mb = GPU_MEMORY_LIMIT_MB;
size_t limit = FLAGS_gpu_memory_limit_mb << 20;
{
ASSERT_TRUE(IsGpuMallocRecorded(DEVICE_ID));
ASSERT_EQ(RecordedGpuMallocSize(DEVICE_ID), 0UL);
}
size_t avail, total;
{
size_t actual_avail, actual_total;
RecordedGpuMemGetInfo(
&avail, &total, &actual_avail, &actual_total, DEVICE_ID);
ASSERT_EQ(total, limit);
ASSERT_EQ(paddle::platform::GpuGetLastError(), gpuSuccess);
}
{
CUDADeviceGuard guard(DEVICE_ID);
GpuMemoryUsage(&avail, &total);
ASSERT_EQ(total, limit);
ASSERT_EQ(paddle::platform::GpuGetLastError(), gpuSuccess);
}
gpuError_t err = gpuSuccess;
void *p1 = nullptr;
size_t size1 = limit / 4 * 3;
{
err = platform::RecordedGpuMalloc(&p1, size1, DEVICE_ID);
ASSERT_EQ(err, gpuSuccess);
ASSERT_EQ(paddle::platform::GpuGetLastError(), gpuSuccess);
ASSERT_NE(p1, nullptr);
ASSERT_EQ(RecordedGpuMallocSize(DEVICE_ID), size1);
}
void *p2 = nullptr;
size_t size2 = limit / 2;
{
err = platform::RecordedGpuMalloc(&p2, size2, DEVICE_ID);
ASSERT_EQ(err, gpuErrorOutOfMemory);
ASSERT_EQ(paddle::platform::GpuGetLastError(), gpuSuccess);
ASSERT_EQ(p2, nullptr);
ASSERT_EQ(RecordedGpuMallocSize(DEVICE_ID), size1);
}
{
platform::RecordedGpuFree(p1, size1, DEVICE_ID);
ASSERT_EQ(RecordedGpuMallocSize(DEVICE_ID), 0UL);
}
{
err = platform::RecordedGpuMalloc(&p2, size2, DEVICE_ID);
ASSERT_EQ(err, gpuSuccess);
ASSERT_EQ(paddle::platform::GpuGetLastError(), gpuSuccess);
ASSERT_NE(p2, nullptr);
ASSERT_EQ(RecordedGpuMallocSize(DEVICE_ID), size2);
}
{
platform::RecordedGpuFree(p2, size2, DEVICE_ID);
ASSERT_EQ(RecordedGpuMallocSize(DEVICE_ID), 0UL);
}
}
} // namespace platform
} // namespace paddle
+46
View File
@@ -0,0 +1,46 @@
// Copyright (c) 2018 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.
#include "paddle/phi/core/platform/timer.h"
#include "gtest/gtest.h"
TEST(Timer, Reset) {
paddle::platform::Timer timeline;
timeline.Start();
sleep(3);
timeline.Pause();
timeline.Reset();
}
TEST(Timer, Start) {
paddle::platform::Timer timeline;
timeline.Start();
sleep(3);
timeline.Pause();
}
TEST(Timer, Pause) {
paddle::platform::Timer timeline;
timeline.Start();
sleep(3);
timeline.Pause();
}
TEST(Timer, Resume) {
paddle::platform::Timer timeline;
timeline.Start();
sleep(3);
timeline.Pause();
timeline.Resume();
}