blob: 92c12bafdd9a35439e97a3a6c3e8c805820aac7a [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 <dmlc/logging.h>
#include <gtest/gtest.h>
#include <tvm/runtime/registry.h>
#include <cmath>
#include <random>
TEST(TextureCopy, HostDeviceRT) {
using namespace tvm;
bool enabled = tvm::runtime::RuntimeEnabled("opencl");
if (!enabled) {
LOG(INFO) << "Skip texture copy test because opencl runtime is disabled.\n";
return;
}
std::vector<int64_t> shape{16, 16, 4};
auto cpu_arr0 = runtime::NDArray::Empty(shape, {kDLFloat, 32, 1}, {kDLCPU, 0});
auto cpu_arr1 = runtime::NDArray::Empty(shape, {kDLFloat, 32, 1}, {kDLCPU, 0});
String mem_scope = "global.texture";
auto opencl_txarr0 = runtime::NDArray::Empty(shape, {kDLFloat, 32, 1}, {kDLOpenCL, 0}, mem_scope);
size_t size = 1;
for (size_t i = 0; i < shape.size(); ++i) {
size *= static_cast<size_t>(shape[i]);
}
std::random_device dev;
std::mt19937 mt(dev());
std::uniform_real_distribution<> random(-10.0, 10.0);
// Random initialize host ndarray
for (size_t i = 0; i < size; i++) {
static_cast<float*>(cpu_arr0->data)[i] = random(mt);
}
// Do a roundtrip from host storage to opencl texture storage and back
cpu_arr0.CopyTo(opencl_txarr0);
opencl_txarr0.CopyTo(cpu_arr1);
for (size_t i = 0; i < size; ++i) {
ICHECK_LT(
std::fabs(static_cast<float*>(cpu_arr1->data)[i] - static_cast<float*>(cpu_arr0->data)[i]),
1e-5);
}
}
TEST(TextureCopy, OverwritePoolSubview) {
using namespace tvm;
bool enabled = tvm::runtime::RuntimeEnabled("opencl");
if (!enabled) {
LOG(INFO) << "Skip texture copy test because opencl runtime is disabled.\n";
return;
}
std::vector<int64_t> shape{16, 16, 4};
std::vector<int64_t> shape_pool{32, 32, 4};
auto cpu_arr0 = runtime::NDArray::Empty(shape, {kDLFloat, 32, 1}, {kDLCPU, 0});
auto cpu_arr1 = runtime::NDArray::Empty(shape, {kDLFloat, 32, 1}, {kDLCPU, 0});
auto cpu_pool0 = runtime::NDArray::Empty(shape_pool, {kDLFloat, 32, 1}, {kDLCPU, 0});
auto cpu_pool1 = runtime::NDArray::Empty(shape_pool, {kDLFloat, 32, 1}, {kDLCPU, 0});
String mem_scope = "global.texture";
auto opencl_txpool =
runtime::NDArray::Empty(shape_pool, {kDLFloat, 32, 1}, {kDLOpenCL, 0}, mem_scope);
auto opencl_txarr0 = opencl_txpool.CreateView(shape, {kDLFloat, 32, 1});
std::random_device dev;
std::mt19937 mt(dev());
std::uniform_real_distribution<> random(-10.0, 10.0);
size_t size = 1;
size_t size_pool = 1;
for (size_t i = 0; i < shape_pool.size(); ++i) {
size *= static_cast<size_t>(shape[i]);
size_pool *= static_cast<size_t>(shape_pool[i]);
}
// Random initialize host pool storage
for (size_t i = 0; i < size_pool; i++) {
static_cast<float*>(cpu_pool0->data)[i] = random(mt);
}
// Random initialize host array
for (int64_t h = 0; h < shape[0]; h++) {
for (int64_t w = 0; w < shape[1]; w++) {
for (int64_t rgba = 0; rgba < shape[2]; rgba++) {
static_cast<float*>(cpu_arr0->data)[shape[1] * shape[2] * h + shape[2] * w + rgba] = 1.1f;
}
}
}
// Copy to texture pool for initialization
cpu_pool0.CopyTo(opencl_txpool);
// Copy host data to subview into texture storage
cpu_arr0.CopyTo(opencl_txarr0);
// Copy modified pool back
opencl_txpool.CopyTo(cpu_pool1);
// Check that modifications to pool follow two dimensional
// strides according to the written texture shape.
for (int64_t h = 0; h < shape_pool[0]; h++) {
for (int64_t w = 0; w < shape_pool[1]; w++) {
for (int64_t rgba = 0; rgba < shape_pool[2]; rgba++) {
size_t i = shape_pool[1] * shape_pool[2] * h + shape_pool[2] * w + rgba;
if (h < shape[0] && w < shape[1] && rgba < shape[2]) {
size_t j = shape[1] * shape[2] * h + shape[2] * w + rgba;
ICHECK_LT(std::fabs(static_cast<float*>(cpu_pool1->data)[i] -
static_cast<float*>(cpu_arr0->data)[j]),
1e-5);
} else {
ICHECK_LT(std::fabs(static_cast<float*>(cpu_pool1->data)[i] -
static_cast<float*>(cpu_pool0->data)[i]),
1e-5);
}
}
}
}
}