日本电子维修技术 显卡<更新>Titan V + Tensor Core小测,想说爱真不




IMG_0216 - 副本.jpg (258.61 KB, 下载次数: 0)

2018-4-4 11:06 上传


想用tensor core,哪怕是最蹩脚最愚蠢的tensor core,只要是tensor core就行了。不过呢也就停留在“想”上,实在没抽空下来研究研究。
昨晚稍微有点时间,就有了个大胆的想法,做个测试。


1,什么是Tensor。
物理学概念,在这里只指代高维度的数据集合。零维标量,一维向量,二维矩阵,三维及以上都可以称为张量tensor,dl中常用的数据体一般是4维的,而最新的capsule是5维数据体。

2,Tensor Core能做哪些处理。
回答这个问题很简单, 因为说明书中写着呢。翻开reference manual第六页,上面清楚的写着,Tensor Core只能应用在两种网络结构上(CNN/RNN),每种网络结构中只适用两种处理,即前馈和后馈。看起来,范围很窄,不过其实这两个处理占据了深度学习非常之高的比重,大概有90%吧。

3,Tensor Core的开启条件。
也就是说,哪些场合可以开启Tensor Core。条件还是很苛刻的,不仅仅是用半精度数据那么简单。
3.1,首先,要为卷积操作设定math type为tensor op,告诉gpu说尽量的使用tensor core,这个很简单,当然如果剩下的条件不符合要求,它还是不会用tensor core的,只是“尽量”使用。

3.2,在执行前馈处理时,采用一种特殊的矩阵乘法算法,这个是最简单的一部,同样是设置一下就行了。no big deal。

3.3,输入/输出/卷积核都必须是fp16格式,也就是半精度浮点格式。设置一下是很容易,不过相应的精度损失需要掂量一下,是否吃的下之类的,当然可以不停的试错来知道。好在大多dl模型是精度不敏感的。

3.4,所有通道必须是8的倍数,这个是很伤,反过来要求模型怎样怎样。什么是通道,比如彩色图片是三通道,就是这个概念。这是一个很苛刻的条件,是一种限制吧。

我为什么知道这么多,因为说明书里面白字黑字写着呢。

4,如何测试。
我没有使用框架进行测试,毕竟框架都做了高度封装,完全不知道他支持到什么程度,这里我使用的是raw cudnn代码。
我仅针对一个函数进行了impl,并做了测试,测试中反复计算同一组数据,可以简单直接的剔除数据交换的耗时,控制了其他变量后,比较也容易了一些。
我测试的是CNN经典的前馈网络算法的cudnn实现:cudnnConvolutionForward,记录的是运行一万次的总运行时间。
下面我一边贴数据,一边说下我的一些个人想法。

TEST环节:

前面说到了经典CNN一般是4维数据集合,但这4维并非平权,而是有分工的。基本上,第一维自成一方,剩下的三维组成另一方。第一维即所谓的batch_size(批次),它代表的是同一时间有多少个样本被一次性塞入GPU,而剩下的三维则是描述一个样本的内在属性。比如一张彩色图片有类似24*24*3的属性,三个维度分别代表长度,宽度和通道(彩色有三个通道)。

这意味测试的时候,主要是调整这两个大方向的平衡,因为在内存大小限定之下,如果样本自身很大,那么一次性能处理的样本就很少了。简单的讲就是这么个理。

第一组,批次设定在512,即一次性处理512个样本。样本的内在属性是128*128*8,可以理解为长宽都为128,通道为8的图片(当然图片没有8维的,这里只是制作的假测试数据,为了满足tensor core启用的第三个条件,即通道必须是8的倍数)

结果如下:
Tensor Core关闭,SP采用半精度浮点计算,fp16 Tensor Core关闭,SP采用单精度计算,fp32Tensor Core开启,并采用半精度计算 ,fp16 78.01s160.20s 69.60s

评论

代码奉上。使用nvcc编译后即可运行,有TODO标签告诉你要改哪些部分。
这个过期了,参考14楼。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <cuda_runtime.h>
#include <assert.h>
#include <cudnn.h>
#include <stddef.h>
#include <iostream>
#include <time.h>
// Linux
#include <sys/time.h>

#define checkCUDNN(expression)                               \
  {                                                          \
    cudnnStatus_t status = (expression);                     \
    if (status != CUDNN_STATUS_SUCCESS) {                    \
      std::cerr << "Error on line " << __LINE__ << ": "      \
                << cudnnGetErrorString(status) << std::endl; \
      std::exit(EXIT_FAILURE);                               \
    }                                                        \
  }

using namespace std;

double get_wall_time()
{
    struct timeval time ;
    if (gettimeofday(&time,NULL)){
        return 0;
    }
    return (double)time.tv_sec + (double)time.tv_usec * .000001;
}

int main( int argc, char** argv )
{

    size_t cudnn_version = cudnnGetVersion();
    size_t cuda_version = cudnnGetCudartVersion();

    cout << "version : cuda runtime: " << cuda_version << " | cudnn: " << cudnn_version << endl;

    cudnnHandle_t cudnn;
    checkCUDNN(cudnnCreate(&cudnn));

    //TODO 4 : The number of Input and Output feature maps is a multiple of 8.
    //TODO 5 : The Filter is of type CUDNN_TENSOR_NCHW or CUDNN_TENSOR_NHWC. When using a filter of type CUDNN_TENSOR_NHWC, Input, Filter and Output data pointers (X, Y, W, dX, dY, and dW as applicable) need to be aligned to 128 bit boundaries.

    const int batch_size = 100;
    const int input_channel = 8;
    const int output_channel = input_channel;
    const int input_height = 256;
    const int input_width = input_height;
    const int kernel_height = 3;
    const int kernel_width = kernel_height;

    //TODO 3 : Input, Filter and Output descriptors (xDesc, yDesc, wDesc, dxDesc, dyDesc and dwDesc as applicable) have dataType = CUDNN_DATA_HALF.

    // INPUT
    cudnnTensorDescriptor_t input_descriptor;
    checkCUDNN(cudnnCreateTensorDescriptor(&input_descriptor));
    checkCUDNN(cudnnSetTensor4dDescriptor(input_descriptor,
                                          /*format=*/CUDNN_TENSOR_NHWC/*batch_size | height | width | channel*/,
                                          /*dataType=*/CUDNN_DATA_HALF/*fp16*/,
                                          /*batch_size=*/batch_size,
                                          /*channels=*/input_channel,
                                          /*image_height=*/input_height,
                                          /*image_width=*/input_width));
    // OUTPUT
    cudnnTensorDescriptor_t output_descriptor;
    checkCUDNN(cudnnCreateTensorDescriptor(&output_descriptor));
    checkCUDNN(cudnnSetTensor4dDescriptor(output_descriptor,
                                          /*format=*/CUDNN_TENSOR_NHWC,
                                          /*dataType=*/CUDNN_DATA_HALF,
                                          /*batch_size=*/batch_size,
                                          /*channels=*/output_channel,
                                          /*image_height=*/input_height,
                                          /*image_width=*/input_width));

    // KERNEL
    cudnnFilterDescriptor_t kernel_descriptor;
    checkCUDNN(cudnnCreateFilterDescriptor(&kernel_descriptor));
    checkCUDNN(cudnnSetFilter4dDescriptor(kernel_descriptor,
                                          /*dataType=*/CUDNN_DATA_HALF,
                                          /*format=*/CUDNN_TENSOR_NCHW,
                                          /*out_channels=*/output_channel,
                                          /*in_channels=*/input_channel,
                                          /*kernel_height=*/kernel_height,
                                          /*kernel_width=*/kernel_width));



    // CONVOLUTION
    cudnnConvolutionDescriptor_t convolution_descriptor;
    checkCUDNN(cudnnCreateConvolutionDescriptor(&convolution_descriptor));
    checkCUDNN(cudnnSetConvolution2dDescriptor(convolution_descriptor,
                                               /*pad_height=*/1/*zero-padding*/,
                                               /*pad_width=*/1/*zero-padding*/,
                                               /*vertical_stride=*/1,
                                               /*horizontal_stride=*/1,
                                               /*dilation_height=*/1/*holing, new kernel height = dilation_factor * ( original_height - 1 ) + 1*/,
                                               /*dilation_width=*/1/*dilation_factor = 1 means no change*/,
                                               /*mode=*/CUDNN_CROSS_CORRELATION,
                                               /*computeType=*/CUDNN_DATA_FLOAT));

    // TODO 1 : cudnnSetConvolutionMathType is called on the appropriate convolution descriptor setting mathType to CUDNN_TENSOR_OP_MATH.

    cudnnSetConvolutionMathType(convolution_descriptor, CUDNN_TENSOR_OP_MATH);
    // cudnnSetConvolutionMathType(convolution_descriptor, CUDNN_DEFAULT_MATH);

    // using 10GB GPU memory for workspace
    float workspace_bytes = 10 * 1024.0f * 1024.0f * 1024.0f;
    void* d_workspace{nullptr};
    cudaMalloc(&d_workspace, workspace_bytes);

    int dummy_input_bytes = batch_size * input_width * input_height * input_channel * sizeof(float);
    int output_bytes = dummy_input_bytes;

    // generate dummy input data
    static float h_dummy_input[batch_size][input_width][input_height][input_channel];
    for (int inner_batch_size = 0; inner_batch_size < batch_size; ++inner_batch_size) {
            for (int inner_height = 0; inner_height < input_height; ++inner_height) {
                    for (int inner_width = 0; inner_width < input_width; ++inner_width) {
                            for (int inner_channel = 0; inner_channel < input_channel; ++inner_channel) {
                                    h_dummy_input[inner_batch_size][inner_height][inner_width][inner_channel] = 0.12345f;
          }
        }
      }
    }

    float* d_dummy_input{nullptr};
    cudaMalloc(&d_dummy_input, dummy_input_bytes);
    cudaMemcpy(d_dummy_input, h_dummy_input, dummy_input_bytes, cudaMemcpyHostToDevice);

    // output data
    float* d_output{nullptr};
    cudaMalloc(&d_output, output_bytes);
    cudaMemset(d_output, 0, output_bytes);

    // 3 by 3 dummy kernel
    const float kernel_template[kernel_width][kernel_height] = {
      {1.1,  1.2, 1.3},
      {1.4, -1.5, 1.6},
      {1.7,  1.8, 1.9}
    };

    float h_dummy_kernel[input_channel][output_channel][kernel_width][kernel_height];
    for (int kernel = 0; kernel < input_channel; ++kernel) {
      for (int channel = 0; channel < output_channel; ++channel) {
        for (int row = 0; row < kernel_width; ++row) {
          for (int column = 0; column < kernel_height; ++column) {
            h_dummy_kernel[kernel][channel][row][column] = kernel_template[row][column];
          }
        }
      }
    }

    float* d_dummy_kernel{nullptr};
    cudaMalloc(&d_dummy_kernel, sizeof(h_dummy_kernel));
    cudaMemcpy(d_dummy_kernel, h_dummy_kernel, sizeof(h_dummy_kernel), cudaMemcpyHostToDevice);

        double start_time = get_wall_time();


        // TODO 2 : cudnnConvolutionForward is called using algo = CUDNN_CONVOLUTION_FWD_ALGO_IMPLICIT_PRECOMP_GEMM.

        // execute
        const float alpha = 1, beta = 0;
    for(int i = 0; i < 10000; i++){

            checkCUDNN(cudnnConvolutionForward(cudnn,
                                                  &alpha,
                                                  input_descriptor,
                                                  d_dummy_input,
                                                  kernel_descriptor,
                                                  d_dummy_kernel,
                                                  convolution_descriptor,
                                                  CUDNN_CONVOLUTION_FWD_ALGO_IMPLICIT_PRECOMP_GEMM,
                                                  d_workspace,
                                                  workspace_bytes,
                                                  &beta,
                                                  output_descriptor,
                                                  d_output));
    }

        double end_time = get_wall_time();
        cout<<"time cost : "<< end_time - start_time <<"s." << endl;

        cudaFree(d_dummy_kernel);
        cudaFree(d_dummy_input);
        cudaFree(d_workspace);

    cudnnDestroyTensorDescriptor(input_descriptor);
    cudnnDestroyTensorDescriptor(output_descriptor);
    cudnnDestroyFilterDescriptor(kernel_descriptor);
    cudnnDestroyConvolutionDescriptor(convolution_descriptor);
    cudnnDestroy(cudnn);
}
复制代码




评论
不想说了,放眼望去全是金币
wifi天线用asus新出的站立式的应该会比较和谐吧


评论
学习了…
说起来gp102和gp100一个支持int8一个支持fp16,就是不给你个全乎的…

评论

Test bench什么型号, 哪里入?

好吧, 坛里搜到了

评论
树导师科普必须顶一个!tensor规模大理论dl算力高,但实际性能要达到理论水平还是需要巨大的优化

评论
等等,树先生
吃瓜群众表示,你这结论容易虐死强迫症
你得直观的告诉大家,搞这个,具体哪款显卡更合适
神马优化之类的不care!


评论
ps. 本来是像下面这样回复的,后面才注意到你用的是CUDNN_CONVOLUTION_FWD_ALGO_IMPLICIT_PRECOMP_GEMM。感觉tensor根本打不过CUDNN_CONVOLUTION_FWD_ALGO_WINOGRAD啊、、、

--------
em......
CUDNN_CONVOLUTION_FWD_ALGO_WINOGRAD优化的太好了吧。。。毕竟tensor不能这样优化了?


曾经对比过:
0   CUDNN_CONVOLUTION_FWD_ALGO_IMPLICIT_GEMM            0:00:28.527458
1   CUDNN_CONVOLUTION_FWD_ALGO_IMPLICIT_PRECOMP_GEMM    0:00:15.827436
6   CUDNN_CONVOLUTION_FWD_ALGO_WINOGRAD                 0:00:10.990773

评论
tensor core目前看来是这次光追技术的关键,老黄下代游戏卡会不会加入tensor core

评论

我试了下,这个wingrad fft 算法真是非常厉害啊,第一组数据,半精度42.299s,单精度38.70s。intel测试了它的i7 975和cudnn [email protected] x(还未应用wingrad算法之前,采用CUDNN_CONVOLUTION_FWD_ALGO_DIRECT)的对比,居然是吊打。
https://arxiv.org/pdf/1509.09308.pdf
https://ai.intel.com/winograd/

1.PNG (118.67 KB, 下载次数: 0)

2018-4-4 18:39 上传



2.PNG (146.22 KB, 下载次数: 0)

2018-4-4 18:39 上传



但这个算法只能应用到small tiles上,需要卷积核很小,比如本贴中用的3x3。



评论

买贵的就行了。

评论



6个字就终结我了?

评论
更新一组新的测试数据,在限定其他参数之下,改变样本尺寸的性能测试。batch_size = 128, input_channel = 8, kernel_size = 3*3

数据
hyper_param        tensor_core        sp_fp16        sp_fp32        sp_fp32_winograd        sp_fp16_winograd
32        1.24807        1.14181        2.25537        0.917808        0.921247
40        1.65325        1.72399        3.33615        1.35495        1.44183
48        2.25016        2.37614        4.67559        1.61697        1.72384
56        2.95046        3.18836        6.35148        2.31077        2.50663
64        3.76574        4.09601        8.22187        2.65733        2.85273
80        5.67113        6.2488        12.7032        4.00899        4.33426
96        8.05187        8.90431        18.2806        5.65286        6.13542
112        10.8515        12.0267        24.6829        7.57724        8.27656
128        14.0958        32.0654        32.1668        9.87031        10.7502
152        19.7337        45.0854        45.233        14.3792        15.7652
176        26.3397        29.4172        60.5687        18.3978        20.1214
200        33.9266        37.9171        78.1265        24.5277        26.8089
224        42.502        47.4743        97.9334        29.6405        32.3995
256        55.5108        32.9729        127.826        38.9912        42.0938


chart化:

chart.jpg (93.91 KB, 下载次数: 1)

2018-4-5 11:13 上传


纵坐标为time cost,越低越好。

结论:
sp的半精度性能在暴走。。。
winograd的优化很强, 现阶段最强。



评论
更新新的测试代码,经过简单的封装后可以进行循环调用。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <cuda_runtime.h>
#include <assert.h>
#include <cudnn.h>
#include <stddef.h>
#include <iostream>
#include <time.h>
#include<vector>
// Linux
#include <sys/time.h>
#include <boost/multi_array.hpp>

using namespace std;

#define checkCUDNN(expression)                               \
  {                                                          \
    cudnnStatus_t status = (expression);                     \
    if (status != CUDNN_STATUS_SUCCESS) {                    \
      cerr << "Error on line " << __LINE__ << ": "           \
                << cudnnGetErrorString(status) << endl;      \
      exit(EXIT_FAILURE);                                    \
    }                                                        \
  }

double get_wall_time()
{
    struct timeval time;
    if (gettimeofday(&time,NULL)){
        return 0;
    }
    return (double)time.tv_sec + (double)time.tv_usec * .000001;
}

cudnnHandle_t cudnn;
cudnnTensorDescriptor_t input_descriptor;
cudnnTensorDescriptor_t output_descriptor;
cudnnFilterDescriptor_t kernel_descriptor;
cudnnConvolutionDescriptor_t convolution_descriptor;

float workspace_bytes;
void* d_workspace{nullptr};
float* d_dummy_input{nullptr};
float* d_dummy_kernel{nullptr};
float* d_output{nullptr};

void post(){
    cout << "version : CUDA runtime: " << cudnnGetVersion() << " | CuDNN: " << cudnnGetCudartVersion() << endl;
}

void initializeDescriptor(
                int batch_size,
                int input_channel,
                int output_channel,
                int input_height,
                int input_width,
                int output_height,
                int output_width,
                int kernel_height,
                int kernel_width,
                cudnnDataType_t dataType,
                cudnnMathType_t mathType){

        checkCUDNN(cudnnCreate(&cudnn));

    //TODO 3 : Input, Filter and Output descriptors (xDesc, yDesc, wDesc, dxDesc, dyDesc and dwDesc as applicable) have dataType = CUDNN_DATA_HALF.

    // INPUT
    checkCUDNN(cudnnCreateTensorDescriptor(&input_descriptor));
    checkCUDNN(cudnnSetTensor4dDescriptor(input_descriptor,
                                          /*format=*/CUDNN_TENSOR_NHWC/*batch_size | height | width | channel*/,
                                          /*dataType=*/dataType/*fp16*/,
                                          /*batch_size=*/batch_size,
                                          /*channels=*/input_channel,
                                          /*image_height=*/input_height,
                                          /*image_width=*/input_width));
    // OUTPUT
    checkCUDNN(cudnnCreateTensorDescriptor(&output_descriptor));
    checkCUDNN(cudnnSetTensor4dDescriptor(output_descriptor,
                                          /*format=*/CUDNN_TENSOR_NHWC,
                                          /*dataType=*/dataType,
                                          /*batch_size=*/batch_size,
                                          /*channels=*/output_channel,
                                          /*image_height=*/output_height,
                                          /*image_width=*/output_width));

    // KERNEL
    checkCUDNN(cudnnCreateFilterDescriptor(&kernel_descriptor));
    checkCUDNN(cudnnSetFilter4dDescriptor(kernel_descriptor,
                                          /*dataType=*/dataType,
                                          /*format=*/CUDNN_TENSOR_NCHW,
                                          /*out_channels=*/output_channel,
                                          /*in_channels=*/input_channel,
                                          /*kernel_height=*/kernel_height,
                                          /*kernel_width=*/kernel_width));

    // CONVOLUTION
    checkCUDNN(cudnnCreateConvolutionDescriptor(&convolution_descriptor));
    checkCUDNN(cudnnSetConvolution2dDescriptor(convolution_descriptor,
                                               /*pad_height=*/1/*zero-padding*/,
                                               /*pad_width=*/1/*zero-padding*/,
                                               /*vertical_stride=*/1,
                                               /*horizontal_stride=*/1,
                                               /*dilation_height=*/1/*holing, new kernel height = dilation_factor * ( original_height - 1 ) + 1*/,
                                               /*dilation_width=*/1/*dilation_factor = 1 means no change*/,
                                               /*mode=*/CUDNN_CROSS_CORRELATION,
                                               /*computeType=*/CUDNN_DATA_FLOAT));

    // TODO 1 : cudnnSetConvolutionMathType is called on the appropriate convolution descriptor setting mathType to CUDNN_TENSOR_OP_MATH.

    cudnnSetConvolutionMathType(convolution_descriptor, mathType);

}

void createDeviceData(
                int batch_size,
                int input_channel,
                int output_channel,
                int input_height,
                int input_width,
                int output_height,
                int output_width,
                int kernel_height,
                int kernel_width){

    // use 10GB GPU memory for workspace
    workspace_bytes = 10 * 1024.0f * 1024.0f * 1024.0f;
    cudaMalloc(&d_workspace, workspace_bytes);

    int dummy_input_bytes = batch_size * input_width * input_height * input_channel * sizeof(float);
    int output_bytes = dummy_input_bytes;

    // generate dummy input data
    boost::multi_array<float, 4> h_dummy_input(boost::extents[batch_size][input_height][input_width][input_channel]);
    for (int inner_batch_size = 0; inner_batch_size < batch_size; ++inner_batch_size) {
            for (int inner_height = 0; inner_height < input_height; ++inner_height) {
                    for (int inner_width = 0; inner_width < input_width; ++inner_width) {
                            for (int inner_channel = 0; inner_channel < input_channel; ++inner_channel) {
                                    h_dummy_input[inner_batch_size][inner_height][inner_width][inner_channel] = 0.12345f;
          }
        }
      }
    }

    cudaMalloc(&d_dummy_input, dummy_input_bytes);
    cudaMemcpy(d_dummy_input, h_dummy_input.data(), dummy_input_bytes, cudaMemcpyHostToDevice);

    // output data
    cudaMalloc(&d_output, output_bytes);
    cudaMemset(d_output, 0, output_bytes);

    // 3 by 3 dummy kernel
    float kernel_template[kernel_width][kernel_height] = {
      {1.1,  1.2, 1.3},
      {1.4, -1.5, 1.6},
      {1.7,  1.8, 1.9}
    };

    float h_dummy_kernel[input_channel][output_channel][kernel_width][kernel_height];
    for (int kernel = 0; kernel < input_channel; ++kernel) {
      for (int channel = 0; channel < output_channel; ++channel) {
        for (int row = 0; row < kernel_width; ++row) {
          for (int column = 0; column < kernel_height; ++column) {
            h_dummy_kernel[kernel][channel][row][column] = kernel_template[row][column];
          }
        }
      }
    }

    cudaMalloc(&d_dummy_kernel, sizeof(h_dummy_kernel));
    cudaMemcpy(d_dummy_kernel, h_dummy_kernel, sizeof(h_dummy_kernel), cudaMemcpyHostToDevice);

}

void freeDeviceData(){
        cudaFree(d_dummy_kernel);
        cudaFree(d_dummy_input);
        cudaFree(d_output);
        cudaFree(d_workspace);
}

int main( int argc, char** argv )
{

        post();

    //TODO 4 : The number of Input and Output feature maps is a multiple of 8.

    int batch_size_hparam[1] = {128};
    int input_channel_hparam[1] = {8};
    int input_height_hparam[14] = {32, 40, 48, 56, 64, 80, 96, 112, 128, 152, 176, 200, 224, 256};

    int kernel_height = 3;
    int kernel_width = kernel_height;

    for(int x = 0; x < 1; x++){

            int batch_size = batch_size_hparam[x];

        for(int y = 0; y < 1; y++){

                int input_channel = input_channel_hparam[y];
                int output_channel = input_channel;

            for(int z = 0; z < 14; z++){
                    int input_height = input_height_hparam[z];
                    int input_width = input_height;
                    int output_height = input_height;
                    int output_width = output_height;

                    // cout << "hyper-param: batch_size = " << batch_size << " | input_channel = " << input_channel << " | input_height = " << input_height << endl;

                initializeDescriptor(
                                batch_size,
                                input_channel,
                                output_channel,
                                input_height,
                                input_width,
                                output_height,
                                output_width,
                                kernel_height,
                                kernel_width,
                                CUDNN_DATA_HALF,
                                CUDNN_DEFAULT_MATH);

                createDeviceData(
                                batch_size,
                                input_channel,
                                output_channel,
                                input_height,
                                input_width,
                                output_height,
                                output_width,
                                kernel_height,
                                kernel_width);

                    double start_time = get_wall_time();
                    // execute
                    const float alpha = 1, beta = 0;
                for(int i = 0; i < 10000; i++){

                        // TODO 2 : cudnnConvolutionForward is called using algo = CUDNN_CONVOLUTION_FWD_ALGO_IMPLICIT_PRECOMP_GEMM.
                        checkCUDNN(cudnnConvolutionForward(cudnn,
                                                              &alpha,
                                                              input_descriptor,
                                                              d_dummy_input,
                                                              kernel_descriptor,
                                                              d_dummy_kernel,
                                                              convolution_descriptor,
                                                              CUDNN_CONVOLUTION_FWD_ALGO_WINOGRAD,
                                                              d_workspace,
                                                              workspace_bytes,
                                                              &beta,
                                                              output_descriptor,
                                                              d_output));
                }
                    double end_time = get_wall_time();

                    // cout<<"time cost : "<< end_time - start_time <<"s." << endl;
                    cout<< end_time - start_time <<endl;

                    freeDeviceData();


            }
        }
    }

    cudnnDestroyTensorDescriptor(input_descriptor);
    cudnnDestroyTensorDescriptor(output_descriptor);
    cudnnDestroyFilterDescriptor(kernel_descriptor);
    cudnnDestroyConvolutionDescriptor(convolution_descriptor);
    cudnnDestroy(cudnn);
}
复制代码



评论
机架哪里买的(⊙_⊙?)

评论
树娘写的都是中文 我却完全看不懂

评论
好奇问下tt5有信仰灯吗

评论

淘宝,bc1。

评论

没有灯。。。

评论

好奇问下 Ubuntu 对 4K 屏支持如何?

评论

应该比windows和mac强50个身位。

评论

这么屌啊……

还是又想骗我去用 Ubuntu……

我对 Ubuntu 的印象还停留在,装好之后第一件事先替换宋体、雅黑什么的……

这些年一直用 Mac,但是系统问题越来越多,一直又下不了决心切到 Windows,核心原因是 Mac 的中文字体和触摸板比 Win 好得多

评论
pascal开始大核心支持FP32:FP16=1:2,软件上有没有屏蔽不知道(有Quadro GP100的可以试试)
三大框架要支持这玩意不知道还需要多久,感觉目前状态下NV还是很难说服大部分人多花一倍多的价格购卖Titan V……
或许该考虑出个16GB/24GB显存的版本

评论
Titan V不是被爆出计算错误么?

评论

即便16.04, 18.04也是一个吊样,虽然已经集成Google noto,但是依然各种问题不断,而且infinality停止维护了,即便想自己折腾都无从动手了。

只是,真正的高手并非只是使用linux系统而已,人家是全英文工作环境,不输入中文,甚至几乎不阅读中文,没有你说的中文烦恼问题。

之所以LINUX显得非常高大上,主要是语言环境,而不是操作系统。

评论

那英文字体在 4K 屏的显示如何?

Ubuntu 这些年绕了太多圈子,unity、upstart 啥的,开发资源都浪费了

评论

从16.04开始集成Google Noto字体了,4K下英文挺漂亮的。

评论

linux的桌面现实可编程,这才是最屌的,windows恐怕只能去写驱动。

评论
   4个字概括,  不觉明历!

评论
学渣路过 电路 电子 维修 我现在把定影部分拆出来了。想换下滚,因为卡纸。但是我发现灯管挡住了。拆不了。不会拆。论坛里的高手拆解过吗? 评论 认真看,认真瞧。果然有收 电路 电子 维修 求创维42c08RD电路图 评论 电视的图纸很少见 评论 电视的图纸很少见 评论 创维的图纸你要说 版号,不然无能为力 评论 板号5800-p42ALM-0050 168P-P42CLM-01
 ·日本中文新闻 唐田绘里香为新剧《极恶女王》剃光头 展现演员决心
·日本中文新闻 真子小室夫妇新居引发隐私担忧
·日本中文新闻 前AKB48成员柏木由纪与搞笑艺人交往曝光
·日本学校 {日本国际学校}梅田インターナショナルスクール
·日本学校 LINE:sm287 陳雨菲、20歳、台湾からの留学生、東京に来たばかり
·日本留学生活 出售平成22年走行48000km 代步小车
·日本华人网络交流 円相場 一時1ドル=140円台まで上昇?
·日本华人网络交流 问日本华人一个问题
·日本旅游代购 富山接机
 ·生活百科 英国转澳大利亚转换插头
·汽车 【求助】修车遇到困难怎么办?

维修经验

CPUcpu-z 1.77版低调发布

日本维修技术更新: New benchmark “submit and compare” feature New clocks dialog reporting all system’s clock speeds in real-time Preliminary support for Intel Kaby Lake AMD Bristol Ridge processors 主要是增加了支持I、A两个新架构的 ...

维修经验

CPU这几天经常开机黑屏,热重启后又正常

日本维修技术这几天经常开机黑屏,热重启后又正常,今天热重启也不管用了。折腾半天总算点亮,显示超频失败,以前出这个画面我是不理它的,直接重启就能正常进系统了,今天不敢托大,因为 ...

维修经验

CPU超频求助!关于华擎H170和6700K

日本维修技术问题见楼主的show贴 https://www.chiphell.com/thread-1634895-1-1.html 这次华擎的H170 Hyper最大的特色应该是自带时钟发生器可以自由超外频 可是楼主好久没有折腾超频了。。。 两图中除了CPU外频 以 ...

维修经验

CPU液态金属会侵蚀cpu核心吗?

日本维修技术前阵子看到有人说,液态金属时间长了会侵蚀cpu铜盖,那么问题来了,这货会不会侵蚀核心呢? 评论 这玩意儿好像只对铝起反应 评论 不是说,cpu的盖子是铜的吗。。。 评论 不会,核 ...

维修经验

CPUm6i究竟支不支持e3 1231v3

日本维修技术官网上看支持列表没写有e3 1231v3,装机帖又有人晒,百度也没个明确答案,那究竟能不能点亮?有在用的chher说一下么 评论 升级最新bios肯定可以支持 评论 我的p67evo官网上也没说支持12 ...

维修经验

CPU华擎 HYPER 妖板 正确玩法

日本维修技术600元的 B150,10相供电,释放洪荒之力 注意必须官网 Beta 区的 BIOS 有 AVX 的 CPU 可能会掉缓存 启动时按 X 键激活 SKY OC,重启后进入 BIOS 160924164727.jpg (95.63 KB, 下载次数: 1) 2016-9-24 17:47 上传 ...

维修经验

CPUE5 2686 V3和i7 6800K如何选择

日本维修技术默认用,不超频,两者功耗是一模一样的 E5 2686 V3:2.0主频,3.5睿频, 18核心36线程 ,45M L3 咸鱼大约2500~3000元 i7 6800K : 3.5主频,3.8睿频 ,6核心12线程 ,盒装3000元 评论 性能应该是26 ...

维修经验

CPUHD530硬解4K能力还是有点弱呀!

日本维修技术播放器用PotPlay 64bit,各种优化后,跑4K @120Hz视频只能到70帧左右的速度,勉强能用! 显示器用的4K的优派VP2780 未标题-1.jpg (211.97 KB, 下载次数: 0) 2016-9-26 21:29 上传 评论 这个估计你没优化 ...

维修经验

CPU6900k 1.25V到4.2体质怎么样

日本维修技术如图,体质怎么样,ring是35,没敢试了,都说ring高了毁硬件 评论 不错的U,但不算雕,上4.4就大雕了,这电压上4.5的目前没见有人发图 评论 谢谢前辈告知 评论 我这个用1.2V超的4.2,R ...

维修经验

CPUI3 6100 华擎B150M pro4超4.5g测试。

日本维修技术看看论坛没多少i3 6100的帖子,就转下自己发的show贴里面的数据,给大家参考下。家里还有当年的神U i3 540 oc 4.5G在给老妈用。 不知道数据上正常吗?有6100的朋友可以告诉下,另外是不有 ...

维修经验

CPU7系u会兼容100系主板吗?

日本维修技术RT,听说要推200系板,100系还能用吗以后。。 评论 兼容的 评论 感谢!以后换u就行了,目前消息200系板会有新的特性吗? 评论 24条PCI-E 3.0通道、支持Intel Optane混合存储技术、十个USB 3 ...

维修经验

CPU有心入5820k了,求教下温度问题

日本维修技术一直徘徊在6700k和5820k之间,6700k现在这德行直接把我推向了5820k啊,从2600k升级上来,三大件都要换,现在唯一疑惑的是IB-E ex这种顶级风冷能不能压住4.5g的5820呢?毕竟刚刚买一个多月。 ...

维修经验

CPU6600&amp;6600K才100的差价

日本维修技术太少了吧。。。 6600.JPG (106.91 KB, 下载次数: 0) 2016-10-1 10:30 上传 评论 毕竟只是i5而已…… 评论 上z170 6600也能超,等于没区别,差价能有100已经不错了 评论 然后又见不超频人士推荐超频 ...