Checkpointing CUTLASS 1.1 release.
This commit is contained in:
@@ -22,9 +22,9 @@
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
**************************************************************************************************/
|
||||
#include <cutlass_unit_test.h>
|
||||
#include "cutlass_unit_test.h"
|
||||
#include <algorithm>
|
||||
#include <tools/test/unit/core/layout_verification.h>
|
||||
#include "tools/test/unit/core/layout_verification.h"
|
||||
|
||||
|
||||
namespace test {
|
||||
|
||||
@@ -29,12 +29,12 @@
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include <cutlass/tensor_view.h>
|
||||
#include "cutlass/tensor_view.h"
|
||||
|
||||
#include <tools/util/half.h>
|
||||
#include <tools/util/host_tensor_view.h>
|
||||
#include <tools/util/tensor_view_io.h>
|
||||
#include <tools/util/type_traits.h>
|
||||
#include "tools/util/half.h"
|
||||
#include "tools/util/host_tensor_view.h"
|
||||
#include "tools/util/tensor_view_io.h"
|
||||
#include "tools/util/type_traits.h"
|
||||
|
||||
namespace test {
|
||||
|
||||
@@ -275,6 +275,8 @@ class VerifyLayout {
|
||||
for (int index = 0; index < count; ++index) {
|
||||
SourceBits element = hash(layout(index));
|
||||
|
||||
// std::cout << " " << index << ": 0x" << std::hex << element << std::dec << std::endl;
|
||||
|
||||
data[index] = element;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,9 +26,9 @@
|
||||
#include <cublas_v2.h>
|
||||
#include <cstring>
|
||||
|
||||
#include <cutlass_unit_test.h>
|
||||
#include <cutlass/predicate_vector.h>
|
||||
#include <tools/util/host_tensor.h>
|
||||
#include "cutlass_unit_test.h"
|
||||
#include "cutlass/predicate_vector.h"
|
||||
#include "tools/util/host_tensor.h"
|
||||
|
||||
namespace test {
|
||||
|
||||
@@ -118,3 +118,126 @@ TEST(PredicateVector, Basic) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(PredicateVector, Count) {
|
||||
|
||||
{
|
||||
typedef cutlass::PredicateVector<4, 8> PredicateVector;
|
||||
EXPECT_EQ(int(PredicateVector::kWordCount), 1)
|
||||
<< "PredicateVector<4, 8> word count: " << PredicateVector::kWordCount;
|
||||
}
|
||||
|
||||
{
|
||||
typedef cutlass::PredicateVector<4, 4> PredicateVector;
|
||||
EXPECT_EQ(int(PredicateVector::kWordCount), 1)
|
||||
<< "PredicateVector<4, 4> word count: " << PredicateVector::kWordCount;
|
||||
}
|
||||
|
||||
{
|
||||
typedef cutlass::PredicateVector<4, 2> PredicateVector;
|
||||
EXPECT_EQ(int(PredicateVector::kWordCount), 1)
|
||||
<< "PredicateVector<4, 2> word count: " << PredicateVector::kWordCount;
|
||||
}
|
||||
|
||||
{
|
||||
typedef cutlass::PredicateVector<4, 1> PredicateVector;
|
||||
EXPECT_EQ(int(PredicateVector::kWordCount), 1)
|
||||
<< "PredicateVector<4, 1> word count: " << PredicateVector::kWordCount;
|
||||
}
|
||||
|
||||
{
|
||||
typedef cutlass::PredicateVector<8, 8> PredicateVector;
|
||||
EXPECT_EQ(int(PredicateVector::kWordCount), 1)
|
||||
<< "PredicateVector<8, 8> word count: " << PredicateVector::kWordCount;
|
||||
}
|
||||
|
||||
{
|
||||
typedef cutlass::PredicateVector<8, 4> PredicateVector;
|
||||
EXPECT_EQ(int(PredicateVector::kWordCount), 1)
|
||||
<< "PredicateVector<8, 4> word count: " << PredicateVector::kWordCount;
|
||||
}
|
||||
|
||||
{
|
||||
typedef cutlass::PredicateVector<8, 2> PredicateVector;
|
||||
EXPECT_EQ(int(PredicateVector::kWordCount), 1)
|
||||
<< "PredicateVector<8, 2> word count: " << PredicateVector::kWordCount;
|
||||
}
|
||||
|
||||
{
|
||||
typedef cutlass::PredicateVector<8, 1> PredicateVector;
|
||||
EXPECT_EQ(int(PredicateVector::kWordCount), 2)
|
||||
<< "PredicateVector<8, 1> word count: " << PredicateVector::kWordCount;
|
||||
}
|
||||
|
||||
{
|
||||
typedef cutlass::PredicateVector<16, 8> PredicateVector;
|
||||
EXPECT_EQ(int(PredicateVector::kWordCount), 1)
|
||||
<< "PredicateVector<16, 8> word count: " << PredicateVector::kWordCount;
|
||||
}
|
||||
|
||||
{
|
||||
typedef cutlass::PredicateVector<16, 4> PredicateVector;
|
||||
EXPECT_EQ(int(PredicateVector::kWordCount), 1)
|
||||
<< "PredicateVector<16, 4> word count: " << PredicateVector::kWordCount;
|
||||
}
|
||||
|
||||
{
|
||||
typedef cutlass::PredicateVector<16, 2> PredicateVector;
|
||||
EXPECT_EQ(int(PredicateVector::kWordCount), 2)
|
||||
<< "PredicateVector<16, 2> word count: " << PredicateVector::kWordCount;
|
||||
}
|
||||
|
||||
{
|
||||
typedef cutlass::PredicateVector<16, 1> PredicateVector;
|
||||
EXPECT_EQ(int(PredicateVector::kWordCount), 4)
|
||||
<< "PredicateVector<16, 1> word count: " << PredicateVector::kWordCount;
|
||||
}
|
||||
|
||||
{
|
||||
typedef cutlass::PredicateVector<32, 8> PredicateVector;
|
||||
EXPECT_EQ(int(PredicateVector::kWordCount), 1)
|
||||
<< "PredicateVector<32, 8> word count: " << PredicateVector::kWordCount;
|
||||
}
|
||||
|
||||
{
|
||||
typedef cutlass::PredicateVector<32, 4> PredicateVector;
|
||||
EXPECT_EQ(int(PredicateVector::kWordCount), 2)
|
||||
<< "PredicateVector<32, 4> word count: " << PredicateVector::kWordCount;
|
||||
}
|
||||
|
||||
{
|
||||
typedef cutlass::PredicateVector<32, 2> PredicateVector;
|
||||
EXPECT_EQ(int(PredicateVector::kWordCount), 4)
|
||||
<< "PredicateVector<32, 2> word count: " << PredicateVector::kWordCount;
|
||||
}
|
||||
|
||||
{
|
||||
typedef cutlass::PredicateVector<32, 1> PredicateVector;
|
||||
EXPECT_EQ(int(PredicateVector::kWordCount), 8)
|
||||
<< "PredicateVector<32, 1> word count: " << PredicateVector::kWordCount;
|
||||
}
|
||||
|
||||
{
|
||||
typedef cutlass::PredicateVector<64, 8> PredicateVector;
|
||||
EXPECT_EQ(int(PredicateVector::kWordCount), 2)
|
||||
<< "PredicateVector<64, 8> word count: " << PredicateVector::kWordCount;
|
||||
}
|
||||
|
||||
{
|
||||
typedef cutlass::PredicateVector<64, 4> PredicateVector;
|
||||
EXPECT_EQ(int(PredicateVector::kWordCount), 4)
|
||||
<< "PredicateVector<64, 4> word count: " << PredicateVector::kWordCount;
|
||||
}
|
||||
|
||||
{
|
||||
typedef cutlass::PredicateVector<64, 2> PredicateVector;
|
||||
EXPECT_EQ(int(PredicateVector::kWordCount), 8)
|
||||
<< "PredicateVector<64, 2> word count: " << PredicateVector::kWordCount;
|
||||
}
|
||||
|
||||
{
|
||||
typedef cutlass::PredicateVector<64, 1> PredicateVector;
|
||||
EXPECT_EQ(int(PredicateVector::kWordCount), 16)
|
||||
<< "PredicateVector<64, 1> word count: " << PredicateVector::kWordCount;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright (c) 2017-2018, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||
* provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
* * Neither the name of the NVIDIA CORPORATION nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TOR (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
**************************************************************************************************/
|
||||
#include "cutlass_unit_test.h"
|
||||
|
||||
#include "cutlass/tensor_ref.h"
|
||||
#include "cutlass/matrix_traits.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TEST(TensorRef, basic_rank2) {
|
||||
int const M = 8;
|
||||
int const N = 16;
|
||||
|
||||
int matrix_data[M * N] = {0};
|
||||
|
||||
cutlass::TensorRef<int, 2> matrix_ref(matrix_data, cutlass::make_Coord(N, 1));
|
||||
for (int m = 0; m < M; ++m) {
|
||||
for (int n = 0; n < N; ++n) {
|
||||
matrix_ref.at(cutlass::make_Coord(m, n)) = m * N + n;
|
||||
}
|
||||
}
|
||||
|
||||
for (int m = 0; m < M; ++m) {
|
||||
for (int n = 0; n < N; ++n) {
|
||||
EXPECT_EQ(matrix_data[m * N + n], int(m * N + n));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TEST(TensorRef, rank2_column_major) {
|
||||
int const M = 8;
|
||||
int const N = 8;
|
||||
|
||||
int matrix_data[M * N];
|
||||
|
||||
cutlass::TensorRef<int, 2, cutlass::MatrixLayout::ColumnMajor> ref(matrix_data, M);
|
||||
|
||||
for (int m = 0; m < M; ++m) {
|
||||
for (int n = 0; n < N; ++n) {
|
||||
ref.at(cutlass::make_Coord(m, n)) = m * N + n;
|
||||
}
|
||||
}
|
||||
|
||||
for (int m = 0; m < M; ++m) {
|
||||
for (int n = 0; n < N; ++n) {
|
||||
EXPECT_EQ(matrix_data[m + n * M], int(m * N + n));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TEST(TensorRef, rank2_row_major) {
|
||||
int const M = 8;
|
||||
int const N = 16;
|
||||
|
||||
int matrix_data[M * N] = { 0 };
|
||||
|
||||
cutlass::TensorRef<int, 2, cutlass::MatrixLayout::RowMajor> ref(matrix_data, N);
|
||||
|
||||
for (int m = 0; m < M; ++m) {
|
||||
for (int n = 0; n < N; ++n) {
|
||||
ref.at(cutlass::make_Coord(m, n)) = m * N + n;
|
||||
}
|
||||
}
|
||||
|
||||
for (int m = 0; m < M; ++m) {
|
||||
for (int n = 0; n < N; ++n) {
|
||||
EXPECT_EQ(matrix_data[m * N + n], int(m * N + n));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TEST(TensorRef, rank2_contiguous_dynamic) {
|
||||
int const M = 8;
|
||||
int const N = 16;
|
||||
|
||||
typedef cutlass::TensorRef<int, 2, cutlass::MatrixLayout::ContiguousLayout> ContiguousTensorRef;
|
||||
|
||||
cutlass::MatrixLayout::Kind layouts[] = {
|
||||
cutlass::MatrixLayout::kColumnMajor,
|
||||
cutlass::MatrixLayout::kRowMajor
|
||||
};
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
|
||||
int matrix_data[M * N] = { 0 };
|
||||
|
||||
int ldm;
|
||||
int row_stride;
|
||||
int col_stride;
|
||||
|
||||
if (layouts[i] == cutlass::MatrixLayout::kColumnMajor) {
|
||||
row_stride = 1;
|
||||
col_stride = M;
|
||||
ldm = col_stride;
|
||||
}
|
||||
else {
|
||||
row_stride = N;
|
||||
col_stride = 1;
|
||||
ldm = row_stride;
|
||||
}
|
||||
|
||||
// Use helper to determine stride vector from leading dimension
|
||||
ContiguousTensorRef ref(
|
||||
matrix_data,
|
||||
cutlass::MatrixLayout::ContiguousLayout::stride(layouts[i], ldm));
|
||||
|
||||
for (int m = 0; m < M; ++m) {
|
||||
for (int n = 0; n < N; ++n) {
|
||||
ref.at(cutlass::make_Coord(m, n)) = m * N + n;
|
||||
}
|
||||
}
|
||||
|
||||
for (int m = 0; m < M; ++m) {
|
||||
for (int n = 0; n < N; ++n) {
|
||||
EXPECT_EQ(matrix_data[m * row_stride + n * col_stride], int(m * N + n));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TEST(TensorRef, rank2_column_major_interleaved) {
|
||||
int const M = 16;
|
||||
int const N = 16;
|
||||
int const kInterleave = 4;
|
||||
|
||||
int matrix_data[M * N] = {0};
|
||||
|
||||
// Define the TensorRefMapFunc for a column-major interleaved matrix format
|
||||
typedef cutlass::MatrixLayout::ColumnMajorInterleaved<kInterleave> TensorRefMapFunc;
|
||||
|
||||
// Construct a TensorRef
|
||||
cutlass::TensorRef<
|
||||
int,
|
||||
2,
|
||||
TensorRefMapFunc> ref(matrix_data, TensorRefMapFunc::stride(M));
|
||||
|
||||
for (int m = 0; m < M; ++m) {
|
||||
for (int n = 0; n < N; ++n) {
|
||||
ref.at(cutlass::make_Coord(m, n)) = m + n * M;
|
||||
}
|
||||
}
|
||||
|
||||
// Verify
|
||||
for (int m = 0; m < M; ++m) {
|
||||
for (int n = 0; n < N; n += kInterleave) {
|
||||
for (int i = 0; i < kInterleave; ++i) {
|
||||
EXPECT_EQ(matrix_data[m * kInterleave + n * M + i], int(m + (n + i) * M));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TEST(TensorRef, rank2_row_major_interleaved) {
|
||||
int const M = 16;
|
||||
int const N = 16;
|
||||
int const kInterleave = 4;
|
||||
|
||||
int matrix_data[M * N] = {0};
|
||||
|
||||
// Define the TensorRefMapFunc for a row-major interleaved matrix format
|
||||
typedef cutlass::MatrixLayout::RowMajorInterleaved<kInterleave> TensorRefMapFunc;
|
||||
|
||||
// Construct a TensorRef
|
||||
cutlass::TensorRef<
|
||||
int,
|
||||
2,
|
||||
TensorRefMapFunc> ref(matrix_data, TensorRefMapFunc::stride(N));
|
||||
|
||||
for (int m = 0; m < M; ++m) {
|
||||
for (int n = 0; n < N; ++n) {
|
||||
ref.at(cutlass::make_Coord(m, n)) = m + n * M;
|
||||
}
|
||||
}
|
||||
|
||||
// Verify
|
||||
for (int m = 0; m < M; m += kInterleave) {
|
||||
for (int n = 0; n < N; ++n) {
|
||||
for (int i = 0; i < kInterleave; ++i) {
|
||||
EXPECT_EQ(matrix_data[m * N + i + n * kInterleave], int((m + i) + n * M));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -0,0 +1,235 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright (c) 2017-2018, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||
* provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
* * Neither the name of the NVIDIA CORPORATION nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TOR (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
**************************************************************************************************/
|
||||
#include "cutlass_unit_test.h"
|
||||
|
||||
#include "cutlass/tensor_view.h"
|
||||
#include "cutlass/matrix_traits.h"
|
||||
|
||||
#include "tools/util/tensor_view_io.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TEST(TensorView, rank2_contiguous_dynamic) {
|
||||
int const M = 8;
|
||||
int const N = 16;
|
||||
|
||||
typedef cutlass::TensorView<int, 2, cutlass::MatrixLayout::ContiguousLayout> ContiguousTensorView;
|
||||
|
||||
cutlass::MatrixLayout::Kind layouts[] = {
|
||||
cutlass::MatrixLayout::kColumnMajor,
|
||||
cutlass::MatrixLayout::kRowMajor
|
||||
};
|
||||
|
||||
cutlass::Coord<2> bounds = cutlass::make_Coord(M - 2, N - 2);
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
|
||||
int matrix_data[M * N] = { 0 };
|
||||
|
||||
int ldm;
|
||||
int row_stride;
|
||||
int col_stride;
|
||||
|
||||
if (layouts[i] == cutlass::MatrixLayout::kColumnMajor) {
|
||||
row_stride = 1;
|
||||
col_stride = M;
|
||||
ldm = col_stride;
|
||||
}
|
||||
else {
|
||||
row_stride = N;
|
||||
col_stride = 1;
|
||||
ldm = row_stride;
|
||||
}
|
||||
|
||||
// Use helper to determine stride vector from leading dimension
|
||||
ContiguousTensorView view(
|
||||
matrix_data,
|
||||
cutlass::MatrixLayout::ContiguousLayout::stride(layouts[i], ldm),
|
||||
bounds);
|
||||
|
||||
ASSERT_TRUE(view.good());
|
||||
|
||||
for (int m = 0; m < M; ++m) {
|
||||
for (int n = 0; n < N; ++n) {
|
||||
cutlass::Coord<2> coord = cutlass::make_Coord(m, n);
|
||||
if (view.contains(coord)) {
|
||||
view.at(coord) = m * N + n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int m = 0; m < M; ++m) {
|
||||
for (int n = 0; n < N; ++n) {
|
||||
int expected = 0;
|
||||
if (m < bounds[0] && n < bounds[1]) {
|
||||
expected = int(m * N + n);
|
||||
}
|
||||
EXPECT_EQ(matrix_data[m * row_stride + n * col_stride], expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Uncomment the following line to observe output from printing TensorView objects
|
||||
//
|
||||
|
||||
// #define OBSERVE_TENSORVIEW_IO // uncomment to enable printing
|
||||
|
||||
#ifdef OBSERVE_TENSORVIEW_IO
|
||||
|
||||
// This test construct a TensorView of rank=2 with matrix layouts known at runtime. This
|
||||
// uses TensorRefMapFunc classes defined in cutlass/matrix_traits.h to define the mapping
|
||||
// from logical tensor indices to storage in memory.
|
||||
//
|
||||
// Helpers in tools/util/tensor_view_io.h print both the logical TensorView and the
|
||||
// linear memory of the tensor.
|
||||
TEST(TensorView, contiguous) {
|
||||
|
||||
int const M = 8;
|
||||
int const N = 16;
|
||||
|
||||
typedef cutlass::TensorView<
|
||||
int32_t,
|
||||
2,
|
||||
cutlass::MatrixLayout::ContiguousLayout> ContiguousTensorView;
|
||||
|
||||
cutlass::MatrixLayout::Kind layouts[] = {
|
||||
cutlass::MatrixLayout::kColumnMajor,
|
||||
cutlass::MatrixLayout::kRowMajor
|
||||
};
|
||||
|
||||
cutlass::Coord<2> bounds = cutlass::make_Coord(M, N);
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
|
||||
int matrix_data[M * N] = { 0 };
|
||||
|
||||
int ldm;
|
||||
int row_stride;
|
||||
int col_stride;
|
||||
|
||||
if (layouts[i] == cutlass::MatrixLayout::kColumnMajor) {
|
||||
row_stride = 1;
|
||||
col_stride = M;
|
||||
ldm = col_stride;
|
||||
}
|
||||
else {
|
||||
row_stride = N;
|
||||
col_stride = 1;
|
||||
ldm = row_stride;
|
||||
}
|
||||
|
||||
// Use helper to determine stride vector from leading dimension
|
||||
ContiguousTensorView view(
|
||||
matrix_data,
|
||||
cutlass::MatrixLayout::ContiguousLayout::stride(layouts[i], ldm),
|
||||
bounds);
|
||||
|
||||
for (int m = 0; m < M; ++m) {
|
||||
for (int n = 0; n < N; ++n) {
|
||||
cutlass::Coord<2> coord = cutlass::make_Coord(m, n);
|
||||
if (view.contains(coord)) {
|
||||
view.at(coord) = m * N + n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "---------\n";
|
||||
std::cout << (layouts[i] == cutlass::MatrixLayout::kColumnMajor ?
|
||||
"Column-major:" : "Row-major:") << "\n\n";
|
||||
|
||||
std::cout << "Logical view:\n";
|
||||
std::cout.width(4);
|
||||
std::cout << view << "\n" << std::endl; // Print TensorView object.
|
||||
|
||||
std::cout << "Linear memory:";
|
||||
for (int idx = 0; idx < view.capacity(); ++idx) {
|
||||
if (!(idx % (layouts[i] == cutlass::MatrixLayout::kColumnMajor ? M : N))) {
|
||||
std::cout << std::endl;
|
||||
}
|
||||
std::cout << std::setw(4) << view.at(idx) << " ";
|
||||
}
|
||||
|
||||
std::cout << "\n" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
// This test is similar to the previous except it uses a column-major, interleaved data
|
||||
// layout. The test prints both the logical representation (a typical column-major matrix)
|
||||
// and a representation of linear memory.
|
||||
//
|
||||
// Note, the interleave=4 structure implies that every four consecutive elements in the
|
||||
// same row shall be adjacent in memory followed by the next row.
|
||||
TEST(TensorView, rank2_column_major_interleaved) {
|
||||
int const M = 16;
|
||||
int const N = 16;
|
||||
int const kInterleave = 4;
|
||||
|
||||
int matrix_data[M * N] = {0};
|
||||
|
||||
cutlass::Coord<2> bounds = cutlass::make_Coord(M, N);
|
||||
|
||||
// Define the TensorRefMapFunc for a column-major interleaved matrix format
|
||||
typedef cutlass::MatrixLayout::ColumnMajorInterleaved<kInterleave> TensorRefMapFunc;
|
||||
|
||||
// Define a TensorView of rank=2 using the column-major interleaved mapping function
|
||||
typedef cutlass::TensorView<
|
||||
int,
|
||||
2,
|
||||
TensorRefMapFunc> InterleavedTensorView;
|
||||
|
||||
InterleavedTensorView view(
|
||||
matrix_data,
|
||||
TensorRefMapFunc::stride(M),
|
||||
bounds);
|
||||
|
||||
// Initialize
|
||||
for (int m = 0; m < M; ++m) {
|
||||
for (int n = 0; n < N; ++n) {
|
||||
view.at(cutlass::make_Coord(m, n)) = m + n * M;
|
||||
}
|
||||
}
|
||||
|
||||
// Print logical view
|
||||
std::cout << "Column-major, interleave=" << kInterleave << " (logical view):\n";
|
||||
|
||||
std::cout << std::setw(4) << view << "\n" << std::endl;
|
||||
|
||||
// Now define a linear view of the same data in memory
|
||||
typedef cutlass::TensorView<int, 2, cutlass::MatrixLayout::RowMajor> LinearTensorView;
|
||||
|
||||
LinearTensorView linear_view(matrix_data, cutlass::make_Coord(N), bounds);
|
||||
|
||||
std::cout << "Linear view in memory:\n";
|
||||
std::cout << std::setw(4) << linear_view << std::endl;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||
* provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
* * Neither the name of the NVIDIA CORPORATION nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without specific prior written
|
||||
* permission.
|
||||
* * Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
* * Neither the name of the NVIDIA CORPORATION nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
@@ -22,29 +22,37 @@
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
**************************************************************************************************/
|
||||
#include <cutlass_unit_test.h>
|
||||
#include <tools/util/host_tensor.h>
|
||||
#include <tools/util/tensor_view_io.h>
|
||||
#include <cutlass/shape.h>
|
||||
#include <cutlass/predicate_vector.h>
|
||||
#include <cutlass/tile_iterator.h>
|
||||
#include <cutlass/tile_traits_standard.h>
|
||||
#include <cutlass/iterator_access.h>
|
||||
#include "cutlass_unit_test.h"
|
||||
#include "tools/util/host_matrix.h"
|
||||
#include "tools/util/tensor_view_io.h"
|
||||
#include "cutlass/shape.h"
|
||||
#include "cutlass/predicate_vector.h"
|
||||
#include "cutlass/tile_iterator.h"
|
||||
#include "cutlass/tile_traits_standard.h"
|
||||
#include "cutlass/iterator_access.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace test {
|
||||
|
||||
template <typename Traits, typename Scalar>
|
||||
__global__ void load_store_global(
|
||||
typename cutlass::TileLoadIterator<Traits, Scalar, cutlass::IteratorAdvance::kH,
|
||||
cutlass::MemorySpace::kGlobal>::Scalar const *input,
|
||||
typename cutlass::TileStoreIterator<Traits, Scalar, cutlass::IteratorAdvance::kH,
|
||||
cutlass::MemorySpace::kGlobal>::Scalar *output
|
||||
) {
|
||||
template <typename Traits, typename Scalar>
|
||||
__global__ void load_store_global(
|
||||
typename cutlass::TileLoadIterator<Traits, Scalar, cutlass::IteratorAdvance::kH,
|
||||
cutlass::MemorySpace::kGlobal>::Scalar const *input,
|
||||
typename cutlass::TileStoreIterator<Traits, Scalar, cutlass::IteratorAdvance::kH,
|
||||
cutlass::MemorySpace::kGlobal>::Scalar *output,
|
||||
int kW,
|
||||
int kH,
|
||||
typename cutlass::TileStoreIterator<Traits, Scalar, cutlass::IteratorAdvance::kH,
|
||||
cutlass::MemorySpace::kGlobal>::Scalar identity = 0
|
||||
) {
|
||||
|
||||
/// Load iterator
|
||||
typedef cutlass::TileLoadIterator<Traits, Scalar, cutlass::IteratorAdvance::kH, cutlass::MemorySpace::kGlobal> LoadIterator;
|
||||
/// Store iterator
|
||||
typedef cutlass::TileStoreIterator<Traits, Scalar, cutlass::IteratorAdvance::kH, cutlass::MemorySpace::kGlobal> StoreIterator;
|
||||
/// Predicate vector
|
||||
typedef typename LoadIterator::PredicateVector PredicateVector;
|
||||
|
||||
typename LoadIterator::Params load_params;
|
||||
typename StoreIterator::Params store_params;
|
||||
@@ -56,98 +64,144 @@ namespace test {
|
||||
|
||||
LoadIterator load_iterator(load_params);
|
||||
StoreIterator store_iterator(store_params);
|
||||
PredicateVector predicates;
|
||||
|
||||
load_iterator.initialize_predicates(predicates.begin(), cutlass::make_Coord(1, kH, kW));
|
||||
|
||||
typename LoadIterator::Fragment fragment;
|
||||
|
||||
load_iterator.load(fragment);
|
||||
store_iterator.store(fragment);
|
||||
load_iterator.load_post_increment(fragment, predicates.begin());
|
||||
store_iterator.store_post_increment(fragment);
|
||||
}
|
||||
|
||||
/// Launches the load_store_global test
|
||||
template <typename Scalar, typename Tile, int kThreadsPerThreadBlock>
|
||||
void run_load_store_global(int kW, int kH) {
|
||||
|
||||
typedef cutlass::TileTraitsStandard<Tile, kThreadsPerThreadBlock> Traits;
|
||||
|
||||
typedef typename cutlass::TypeTraits<Scalar>::device_type ScalarDevice;
|
||||
|
||||
cutlass::HostMatrix<Scalar> input;
|
||||
cutlass::HostMatrix<Scalar> output;
|
||||
|
||||
input.resize(cutlass::make_Coord(Tile::kW, Tile::kH), cutlass::MatrixLayout::kColumnMajor);
|
||||
output.resize(cutlass::make_Coord(Tile::kW, Tile::kH), cutlass::MatrixLayout::kColumnMajor);
|
||||
|
||||
input.fill_linear(cutlass::make_Coord(1, Tile::kW));
|
||||
output.fill(0);
|
||||
|
||||
test::load_store_global<Traits, ScalarDevice> <<<
|
||||
dim3(1, 1, 1),
|
||||
dim3(kThreadsPerThreadBlock, 1)
|
||||
>>>(input.device_data(), output.device_data(), kW, kH);
|
||||
|
||||
cudaError_t result = cudaDeviceSynchronize();
|
||||
|
||||
ASSERT_EQ(result, cudaSuccess) << "\nCUDA kernel launch error: " << cudaGetErrorString(result)
|
||||
<< "\n";
|
||||
output.sync_host();
|
||||
|
||||
bool passed = true;
|
||||
for(int i = 0; i < Tile::kW; ++i) {
|
||||
for(int j = 0; j < Tile::kH; ++j) {
|
||||
if(i < kW && j < kH && output.at(cutlass::make_Coord(i, j)) != Scalar(Tile::kW*j+i)){
|
||||
std::cout << "FAILED: (" << i << ", " << j
|
||||
<< ") -- expected: " << (Tile::kW*j+i)
|
||||
<< ", actual: " << output.at(cutlass::make_Coord(i, j))
|
||||
<< std::endl;
|
||||
passed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_TRUE(passed);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TEST(TileIterator, tile_128x8_contiguous) {
|
||||
|
||||
static int const M = 128;
|
||||
static int const N = 1;
|
||||
static int const K = 8;
|
||||
|
||||
static int const kThreads = M;
|
||||
|
||||
typedef cutlass::Shape<K, N, M> ThreadBlockTile;
|
||||
|
||||
typedef cutlass::TileTraitsStandard<cutlass::Shape<N, K, M>, kThreads> Traits;
|
||||
|
||||
cutlass::HostTensor<float> input;
|
||||
cutlass::HostTensor<float> output;
|
||||
|
||||
input.resize_matrix(ThreadBlockTile::kW, ThreadBlockTile::kD,
|
||||
cutlass::MatrixLayout::kColumnMajor);
|
||||
|
||||
output.resize_matrix(ThreadBlockTile::kW, ThreadBlockTile::kD,
|
||||
cutlass::MatrixLayout::kColumnMajor);
|
||||
|
||||
input.fill_linear(cutlass::make_Coord(1, 1, ThreadBlockTile::kW, 1));
|
||||
output.fill(0);
|
||||
|
||||
test::load_store_global< Traits, float ><<<
|
||||
dim3(1,1,1),
|
||||
dim3(kThreads, 1)
|
||||
>>>(
|
||||
input.device_data(),
|
||||
output.device_data()
|
||||
);
|
||||
|
||||
cudaError_t result = cudaDeviceSynchronize();
|
||||
ASSERT_EQ(result, cudaSuccess) << "\nCUDA kernel launch error: " << cudaGetErrorString(result)
|
||||
<< "\n";
|
||||
output.sync_host();
|
||||
|
||||
EXPECT_TRUE(input.bit_equals(output));
|
||||
|
||||
run_load_store_global<float, cutlass::Shape<1, 8, 128>, 128>(128, 8);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TEST(TileIterator, tile_128x8_rake) {
|
||||
|
||||
static int const M = 128;
|
||||
static int const N = 1;
|
||||
static int const K = 8;
|
||||
|
||||
static int const kThreads = 32;
|
||||
|
||||
typedef cutlass::Shape<K, N, M> ThreadBlockTile;
|
||||
|
||||
typedef cutlass::TileTraitsStandard<cutlass::Shape<N, K, M>, kThreads> Traits;
|
||||
|
||||
cutlass::HostTensor<float> input;
|
||||
cutlass::HostTensor<float> output;
|
||||
|
||||
input.resize_matrix(ThreadBlockTile::kW, ThreadBlockTile::kD,
|
||||
cutlass::MatrixLayout::kColumnMajor);
|
||||
|
||||
output.resize_matrix(ThreadBlockTile::kW, ThreadBlockTile::kD,
|
||||
cutlass::MatrixLayout::kColumnMajor);
|
||||
|
||||
input.fill_linear(cutlass::make_Coord(1, 1, ThreadBlockTile::kW, 1));
|
||||
output.fill(0);
|
||||
|
||||
test::load_store_global< Traits, float ><<<
|
||||
dim3(1,1,1),
|
||||
dim3(kThreads, 1)
|
||||
>>>(
|
||||
input.device_data(),
|
||||
output.device_data()
|
||||
);
|
||||
|
||||
cudaError_t result = cudaDeviceSynchronize();
|
||||
ASSERT_EQ(result, cudaSuccess) << "\nCUDA kernel launch error: " << cudaGetErrorString(result)
|
||||
<< "\n";
|
||||
|
||||
output.sync_host();
|
||||
|
||||
EXPECT_TRUE(input.bit_equals(output));
|
||||
|
||||
run_load_store_global<float, cutlass::Shape<1, 8, 128>, 32>(128, 8);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TEST(TileIterator, tile_127x8_contiguous) {
|
||||
run_load_store_global<float, cutlass::Shape<1, 8, 128>, 128>(127, 8);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TEST(TileIterator, tile_129x8_contiguous) {
|
||||
run_load_store_global<float, cutlass::Shape<1, 8, 128>, 128>(129, 8);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TEST(TileIterator, tile_112x8_contiguous) {
|
||||
run_load_store_global<float, cutlass::Shape<1, 8, 128>, 128>(112, 8);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TEST(TileIterator, tile_67x8_contiguous) {
|
||||
run_load_store_global<float, cutlass::Shape<1, 8, 128>, 128>(67, 8);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TEST(TileIterator, tile_113x7_contiguous) {
|
||||
run_load_store_global<float, cutlass::Shape<1, 8, 128>, 128>(113, 7);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TEST(TileIterator, tile_113x10_contiguous) {
|
||||
run_load_store_global<float, cutlass::Shape<1, 8, 128>, 128>(113, 10);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TEST(TileIterator, tile_131x7_contiguous) {
|
||||
run_load_store_global<float, cutlass::Shape<1, 8, 128>, 128>(131, 7);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TEST(TileIterator, tile_131x9_contiguous) {
|
||||
run_load_store_global<float, cutlass::Shape<1, 8, 128>, 128>(131, 9);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Half
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TEST(TileIterator, tile_128x8_contiguous_f16) {
|
||||
run_load_store_global<cutlass::half_t, cutlass::Shape<1, 8, 128>, 128>(128, 8);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Double
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TEST(TileIterator, tile_128x8_contiguous_f64) {
|
||||
run_load_store_global<double, cutlass::Shape<1, 8, 128>, 128>(128, 8);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Int
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TEST(TileIterator, tile_128x8_contiguous_s32) {
|
||||
run_load_store_global<int, cutlass::Shape<1, 8, 128>, 128>(128, 8);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
} // namespace test
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
/***************************************************************************************************
|
||||
* Copyright (c) 2017-2018, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||
* provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice, this list of
|
||||
* conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
* * Neither the name of the NVIDIA CORPORATION nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TOR (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
**************************************************************************************************/
|
||||
#include "cutlass_unit_test.h"
|
||||
#include "tools/util/host_matrix.h"
|
||||
#include "tools/util/tensor_view_io.h"
|
||||
#include "cutlass/shape.h"
|
||||
#include "cutlass/predicate_vector.h"
|
||||
#include "cutlass/tile_iterator.h"
|
||||
#include "cutlass/tile_traits_standard.h"
|
||||
|
||||
#include "cutlass/zip_tile_iterator.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace test {
|
||||
|
||||
/// Kernel which can use tile iterators and zip iterators
|
||||
template <typename LoadIterator, typename StoreIterator>
|
||||
__global__ void zip_iterator_kernel(
|
||||
typename LoadIterator::Params load_params,
|
||||
typename StoreIterator::Params store_params) {
|
||||
|
||||
LoadIterator load_iterator(load_params);
|
||||
StoreIterator store_iterator(store_params);
|
||||
|
||||
typename LoadIterator::Fragment fragment;
|
||||
|
||||
load_iterator.load_post_increment(fragment);
|
||||
store_iterator.store_post_increment(fragment);
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Test framework
|
||||
template <typename Scalar, typename Shape>
|
||||
struct ZipIteratorTest {
|
||||
|
||||
//
|
||||
// Type definitions
|
||||
//
|
||||
|
||||
static int const kThreadCount = 128;
|
||||
|
||||
typedef cutlass::TileTraitsStandard<Shape, kThreadCount> TileTraits;
|
||||
|
||||
typedef cutlass::TileLoadIterator<TileTraits, Scalar> ScalarLoadIterator;
|
||||
typedef cutlass::TileStoreIterator<TileTraits, Scalar> ScalarStoreIterator;
|
||||
|
||||
typedef cutlass::ZipTileIterator<ScalarLoadIterator, ScalarLoadIterator> ZipLoadIterator;
|
||||
typedef cutlass::ZipTileIterator<ScalarStoreIterator, ScalarStoreIterator> ZipStoreIterator;
|
||||
|
||||
//
|
||||
// Data members
|
||||
//
|
||||
|
||||
cutlass::HostMatrix<Scalar> tensor_source_real;
|
||||
cutlass::HostMatrix<Scalar> tensor_source_imag;
|
||||
|
||||
cutlass::HostMatrix<Scalar> tensor_dest_real;
|
||||
cutlass::HostMatrix<Scalar> tensor_dest_imag;
|
||||
|
||||
//
|
||||
// Methods
|
||||
//
|
||||
|
||||
/// Ctor
|
||||
ZipIteratorTest() {
|
||||
|
||||
tensor_source_real.resize(cutlass::make_Coord(Shape::kH, Shape::kW), cutlass::MatrixLayout::kRowMajor);
|
||||
tensor_source_imag.resize(cutlass::make_Coord(Shape::kH, Shape::kW), cutlass::MatrixLayout::kRowMajor);
|
||||
tensor_dest_real.resize(cutlass::make_Coord(Shape::kH, Shape::kW), cutlass::MatrixLayout::kRowMajor);
|
||||
tensor_dest_imag.resize(cutlass::make_Coord(Shape::kH, Shape::kW), cutlass::MatrixLayout::kRowMajor);
|
||||
}
|
||||
|
||||
/// Runs test
|
||||
void run() {
|
||||
|
||||
tensor_source_real.fill_sequential();
|
||||
tensor_source_imag.fill_sequential();
|
||||
|
||||
tensor_dest_real.fill(0);
|
||||
tensor_dest_imag.fill(0);
|
||||
|
||||
tensor_source_real.sync_device();
|
||||
tensor_source_imag.sync_device();
|
||||
tensor_dest_real.sync_device();
|
||||
tensor_dest_imag.sync_device();
|
||||
|
||||
|
||||
typename ZipLoadIterator::Params load_params;
|
||||
typename ZipStoreIterator::Params store_params;
|
||||
|
||||
load_params.first.initialize(
|
||||
tensor_source_real.device_data(),
|
||||
0,
|
||||
tensor_source_real.leading_dim(),
|
||||
1
|
||||
);
|
||||
|
||||
load_params.second.initialize(
|
||||
tensor_source_imag.device_data(),
|
||||
0,
|
||||
tensor_source_real.leading_dim(),
|
||||
1
|
||||
);
|
||||
|
||||
store_params.first.initialize(
|
||||
tensor_dest_real.device_data(),
|
||||
0,
|
||||
tensor_source_real.leading_dim(),
|
||||
1
|
||||
);
|
||||
|
||||
store_params.second.initialize(
|
||||
tensor_dest_imag.device_data(),
|
||||
0,
|
||||
tensor_source_real.leading_dim(),
|
||||
1
|
||||
);
|
||||
|
||||
/// Launch kernel
|
||||
test::zip_iterator_kernel<ZipLoadIterator, ZipStoreIterator><<<
|
||||
dim3(1,1),
|
||||
dim3(kThreadCount, 1)
|
||||
>>>(
|
||||
load_params,
|
||||
store_params
|
||||
);
|
||||
|
||||
cudaError_t result = cudaGetLastError();
|
||||
EXPECT_EQ(result, cudaSuccess) << "Error on kernel launch: " << cudaGetErrorString(result);
|
||||
|
||||
tensor_dest_real.sync_host();
|
||||
tensor_dest_imag.sync_host();
|
||||
|
||||
// Verify equivalence
|
||||
EXPECT_TRUE(tensor_dest_real.bit_equals(tensor_source_real));
|
||||
EXPECT_TRUE(tensor_dest_imag.bit_equals(tensor_source_imag));
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TEST(ZipTileIterator, tile_128x8) {
|
||||
ZipIteratorTest<int, cutlass::Shape<1, 8, 128> >().run();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Reference in New Issue
Block a user