《一次性解释清楚什么是gpu挖矿》

做一个牛逼闪闪的程序员,指的不是技术,是蔑视技术的态度。
T a n g s h u n c a i \color{#222514}{-}\color{#222514}{-}\color{#222514}{-}\color{#222514}{-}\color{#4285f4}{T}\color{#ea4335}{a}\color{#fbbc05}{n}\color{#4285f4}{g}\color{#34a853}{s}\color{#ea4335}{h}\color{#4285f4}{u}\color{#fbbc05}{n}\color{#34a853}{c}\color{#ea4335}{a}\color{#fbbc05}{i}

cpu与gpu的区别:

  • cpu适合做不同的任务,gpu适合做重复性比较多的工作。
  • cpu是领导,gpu是板砖的。

以下图示分别是gpu和gpu的硬件组成:
在这里插入图片描述

在这里插入图片描述

从组成模块上面看,gpu的算数逻辑单元数量众多,是cpu的几百倍。对于重复性的计算,gpu相当于有1024个核在并发执行(注意:此处是于操作系统的并发是两个不同的概念,此处是同一时刻的并发,而操作系统是一个时间段的并发),而cpu只有4个核在执行。速度上面自然是gpu快很多。

以下是实物图:
在这里插入图片描述
在这里插入图片描述

gpu执行时间对比:

1万次累加运算:

root@-desktop:~/capture/cuda# ./main 
GPU运行时间为:71ms
CPU运行时间为:3865ms

root@-desktop:~/capture/cuda#

10万次累加运算:

root@-desktop:~/capture/cuda# ./main 
GPU运行时间为:66ms

CPU运行时间为:38538ms
root@-desktop:~/capture/cuda# 

可以发现,在一定次数范围内,gpu的性能尚未用完,因此时间稳定在70ms(70ms包括数据从cpu到gpu,gpu运算时间,结果从gpu到cpu的时间)。

执行环境

vmware虚拟机,ubuntu系统。
cuda库

cuda库安装

apt install cuda-nvcc-10-0

设置动态库加载路径,命令加载路径:

root@-desktop:~/# tail /root/.bashrc 
# enable programmable completion features (you don't need to enable
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
# sources /etc/bash.bashrc).
#if [ -f /etc/bash_completion ] && ! shopt -oq posix; then
#    . /etc/bash_completion
#fi

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib/
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/cuda/lib/
export PATH=$PATH:/usr/local/cuda/bin
root@jack-desktop:~/#

代码如下:

/*kernel.cu*/
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include "main.h"
#include <stdio.h>

inline void checkCudaErrors(cudaError err)//错误处理函数
{
        if (cudaSuccess != err)
        {
                fprintf(stderr, "CUDA Runtime API error: %s.\n", cudaGetErrorString(err));
                return;
        }
}

__global__ void add(int *a,int *b,int *c)//处理核函数
{
        int tid = blockIdx.x*blockDim.x+threadIdx.x;
        for (size_t k = 0; k < 50000; k++)
        {
                c[tid] = a[tid] + b[tid];
        }
}

extern "C" int runtest(int *host_a, int *host_b, int *host_c)
{
        int *dev_a, *dev_b, *dev_c;

        checkCudaErrors(cudaMalloc((void**)&dev_a, sizeof(int)* datasize));//分配显卡内存
        checkCudaErrors(cudaMalloc((void**)&dev_b, sizeof(int)* datasize));
        checkCudaErrors(cudaMalloc((void**)&dev_c, sizeof(int)* datasize));

        checkCudaErrors(cudaMemcpy(dev_a, host_a, sizeof(int)* datasize, cudaMemcpyHostToDevice));//将主机待处理数据内存块复制到显卡内存中
        checkCudaErrors(cudaMemcpy(dev_b, host_b, sizeof(int)* datasize, cudaMemcpyHostToDevice));

        add << <datasize / 100, 100 >> >(dev_a, dev_b, dev_c);//调用显卡处理数据
        checkCudaErrors(cudaMemcpy(host_c, dev_c, sizeof(int)* datasize, cudaMemcpyDeviceToHost));//将显卡处理完数据拷回来

        cudaFree(dev_a);//清理显卡内存
        cudaFree(dev_b);
        cudaFree(dev_c);
        return 0;
}

// main.h
#ifndef __MAIN_H__
#define __MAIN_H__

#define datasize        100 * 1000

#endif

//main.cc
#include "main.h"
#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
#include <time.h>

extern "C" int runtest(int *host_a, int *host_b, int *host_c);//显卡处理函数

int main()
{
        int a[datasize], b[datasize], c[datasize];
        for (size_t i = 0; i < datasize; i++)
        {
                a[i] = i;
                b[i] = i*i;
        }

        long now1 = clock();//存储图像处理开始时间  
        runtest(a,b,c);//调用显卡加速
        printf("GPU运行时间为:%dms\n", int(((double)(clock() - now1)) / CLOCKS_PER_SEC * 1000));//输出GPU处理时间

        long now2 = clock();//存储图像处理开始时间  
        for (size_t i = 0; i < datasize; i++)
        {
                for (size_t k = 0; k < 50000; k++)
                {
                        c[i] = (a[i] + b[i]);
                }
        }
        printf("CPU运行时间为:%dms\n", int(((double)(clock() - now2)) / CLOCKS_PER_SEC * 1000));//输出GPU处理时间


        /*for (size_t i = 0; i < 100; i++)//查看计算结果
          {
          printf("%d+%d=%d\n", a[i], b[i], c[i]);
          }*/

        getchar();
        return 0;
}

Makefile

all:
        nvcc -c kernel.cu
        g++ -std=c++11 -c main.cc
        g++ -std=c++11 -o main main.o kernel.o -lcudart -L/usr/local/cuda/lib64
clean:
        rm -rf main

区块链挖矿,就是通过碰撞方法,计算出一个符合哈希值的输入,最先算出合法输入的节点被投票成功后,取得记账的主导权,并获得token奖励。 gpu相对于cpu,可以显著的提高哈希运算的效率。
不过说白了,gpu挖矿也没有多少复杂之处。

对于编写服务器的程序员来说,可以在代码中加入gpu来执行循环运算,以节省cpu的宝贵时间,这比一些动不动就大谈协程,http3.0的人要实在一些。

发布了95 篇原创文章 · 获赞 75 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/jacky128256/article/details/105569668
今日推荐