Checkpointing CUTLASS 1.1 release.

This commit is contained in:
akerr
2018-09-18 16:58:03 -07:00
parent cf0301e00f
commit 461f417b9d
193 changed files with 29495 additions and 4770 deletions
+2 -2
View File
@@ -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 {
+7 -5
View File
@@ -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;
}
}
+126 -3
View File
@@ -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;
}
}
+220
View File
@@ -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));
}
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
+235
View File
@@ -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
////////////////////////////////////////////////////////////////////////////////////////////////////
+156 -102
View File
@@ -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
+173
View File
@@ -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();
}
////////////////////////////////////////////////////////////////////////////////////////////////////