3.9 EXERCISES

  1. 矩阵加法需要两个输入矩阵A和B,并产生一个输出矩阵C。输出矩阵C的每个元素都是输入矩阵A和B的相应元素的总和,即C[i][j] = A[i][j] + B[i][j]。为了简单起见,我们将只处理元素为单精度浮点数的平方矩阵。编写一个矩阵加法内核和主机stub函数,可以使用四个参数调用:指针到输出矩阵、指针到第一个输入矩阵、指针到第二个输入矩阵以及每个维度中的元素数量。按照以下说明操作:
#include <stdio.h>
#include <cuda_runtime.h>

// CUDA内核函数定义
__global__ void matrixAdd(float *C, const float *A, const float *B, int N) {
    int row = blockIdx.y * blockDim.y + threadIdx.y;
    int col = blockIdx.x * blockDim.x + threadIdx.x;

    if (row < N && col < N) {
        int idx = row * N + col;
        C[idx] = A[idx] + B[idx];
    }
}

int main() {
    int N = 256; // 矩阵大小为 N x N
    size_t bytes = N * N * sizeof(float);

    // 分配主机内存
    float *h_A = (float*)malloc(bytes);
    float *h_B = (float*)malloc(bytes);
    float *h_C = (float*)malloc(bytes);

    // 初始化输入矩阵
    for (int i = 0; i < N * N; i++) {
        h_A[i] = static_cast<float>(i);
        h_B[i] = static_cast<float>(i);
    }

    // 分配设备内存
    float *d_A, *d_B, *d_C;
    cudaMalloc(&d_A, bytes);
    cudaMalloc(&d_B, bytes);
    cudaMalloc(&d_C, bytes);

    // 复制数据从主机到设备
    cudaMemcpy(d_A, h_A, bytes, cudaMemcpyHostToDevice);
    cudaMemcpy(d_B, h_B, bytes, cudaMemcpyHostToDevice);

    // 设置线程块和网格大小
    dim3 threadsPerBlock(16, 16);
    dim3 blocksPerGrid((N + threadsPerBlock.x - 1) / threadsPerBlock.x,
                       (N + threadsPerBlock.y - 1) / threadsPerBlock.y);

    // 执行内核函数
    matrixAdd<<<blocksPerGrid, threadsPerBlock>>>(d_C, d_A, d_B, N);

    // 等待CUDA完成并检查错误
    cudaDeviceSynchronize();
    cudaError_t error = cudaGetLastError();
    if (error != cudaSuccess) {
        fprintf(stderr, "CUDA error: %s\n", cudaGetErrorString(error));
        // 清理
        cudaFree(d_A);
        cudaFree(d_B);
        cudaFree(d_C);
        free(h_A);
        free(h_B);
        free(h_C);
        return -1;
    }

    // 将结果复制回主机
    cudaMemcpy(h_C, d_C, bytes, cudaMemcpyDeviceToHost);

    // 验证结果
    for (int i = 0; i < N * N; i++) {
        if (h_C[i] != h_A[i] + h_B[i]) {
            fprintf(stderr, "Result verification failed at element %d!\n", i);
            return -1;
        }
    }
    printf("Test PASSED\n");

    // 清理
    cudaFree(d_A);
    cudaFree(d_B);
    cudaFree(d_C);
    free(h_A);
    free(h_B);
    free(h_C);

    return 0;
}
这段代码首先定义了一个matrixAdd内核,它计算两个矩阵的和,并将结果存储在输出矩阵中。然后在main函数中,它创建了两个输入矩阵和一个输出矩阵,将它们复制到设备内存中,调用内核函数,并将结果复制回主机内存。最后,它验证结果并清理分配的内存。

  1. 矩阵-向量乘法接受输入矩阵B和向量C,并产生一个输出向量A。输出向量A的每个元素都是输入矩阵B和C的一行的点积,即 A[i] = ∑j B[i][j] + C[j]。为了简单起见,我们将只处理元素为单精度浮点数的平方矩阵。编写一个矩阵向量乘法内核和一个主机存根函数,该函数可以使用四个参数调用:指针到输出矩阵、指针到输入矩阵、指针到输入向量以及每个维度的元素数量。使用一个线程来计算输出矢量元素。
#include <stdio.h>
#include <cuda_runtime.h>

// CUDA内核函数定义
__global__ void matrixVectorMultiply(float *A, const float *B, const float *C, int N) {
    int row = blockIdx.x * blockDim.x + threadIdx.x;

    if (row < N) {
        float sum = 0.0f;
        for (int j = 0; j < N; ++j) {
            sum += B[row * N + j] * C[j];
        }
        A[row] = sum;
    }
}

int main() {
    int N = 256; // 矩阵大小为 N x N
    size_t sizeMatrix = N * N * sizeof(float);
    size_t sizeVector = N * sizeof(float);

    // 分配主机内存
    float *h_B = (float*)malloc(sizeMatrix);
    float *h_C = (float*)malloc(sizeVector);
    float *h_A = (float*)malloc(sizeVector);

    // 初始化输入矩阵B和向量C
    for (int i = 0; i < N * N; i++) {
        h_B[i] = static_cast<float>(i);
    }
    for (int i = 0; i < N; i++) {
        h_C[i] = static_cast<float>(i);
    }

    // 分配设备内存
    float *d_B, *d_C, *d_A;
    cudaMalloc(&d_B, sizeMatrix);
    cudaMalloc(&d_C, sizeVector);
    cudaMalloc(&d_A, sizeVector);

    // 复制数据从主机到设备
    cudaMemcpy(d_B, h_B, sizeMatrix, cudaMemcpyHostToDevice);
    cudaMemcpy(d_C, h_C, sizeVector, cudaMemcpyHostToDevice);

    // 设置线程块和网格大小
    int threadsPerBlock = 256;
    int blocksPerGrid = (N + threadsPerBlock - 1) / threadsPerBlock;

    // 执行内核函数
    matrixVectorMultiply<<<blocksPerGrid, threadsPerBlock>>>(d_A, d_B, d_C, N);

    // 等待CUDA完成并检查错误
    cudaDeviceSynchronize();
    cudaError_t error = cudaGetLastError();
    if (error != cudaSuccess) {
        fprintf(stderr, "CUDA error: %s\n", cudaGetErrorString(error));
        // 清理
        cudaFree(d_B);
        cudaFree(d_C);
        cudaFree(d_A);
        free(h_B);
        free(h_C);
        free(h_A);
        return -1;
    }

    // 将结果复制回主机
    cudaMemcpy(h_A, d_A, sizeVector, cudaMemcpyDeviceToHost);

    // 验证结果(这里跳过了验证步骤)

    // 清理
    cudaFree(d_B);
    cudaFree(d_C);
    cudaFree(d_A);
    free(h_B);
    free(h_C);
    free(h_A);

    return 0;
}
  1. 如果CUDA设备的SM最多可以占用1536个线程和最多4个线程块。以下哪个块配置会导致SM中线程数量最多?
    在这里插入图片描述
    答:C 。3*512

  2. 对于向量加法,假设向量长度为2000,每个线程计算一个输出元素,线程块大小为512个线程。网格中将有多少个线程?
    在这里插入图片描述
    答:2048

  3. ***关于上一个问题,由于矢量长度的边界检查,您预计有多少warp发散?(存疑)
    在这里插入图片描述
    答:A.1

因为即便在最后一个线程块中有一些线程不执行实际的向量加法操作,所有的线程都会执行相同的边界检查逻辑,因此没有warp发散。

  1. 您需要编写一个在大小为400 x 900像素的图像上操作的kernel。您想为每个像素分配一个线程。您希望您的线程块是正方形的,并使用设备上每个块的最大线程数(您的设备具有计算能力3.0)。您将如何选择内核的网格尺寸和块尺寸?

对于具有计算能力3.0的NVIDIA GPU,每个线程块最多可以有1024个线程。由于您想要使用正方形的线程块,因此您应该选择一个线程块的尺寸,其边长是1024的平方根。1024的平方根是32,所以您可以选择一个线程块的尺寸为32x32,这样每个块就有 32 × 32 = 1024 32 \times 32 = 1024 32×32=1024个线程,这是最大线程数。
对于一个400x900像素的图像,您需要足够的块来覆盖所有的像素。通过将图像的尺寸除以线程块的尺寸,您可以得到网格的尺寸:

  • 对于宽度(900像素),您需要 ⌈ 900 32 ⌉ = 29 \lceil \frac{900}{32} \rceil = 29 32900=29 个块(因为900不能被32整除,所以您需要向上取整)。
  • 对于高度(400像素),您需要 ⌈ 400 32 ⌉ = 13 \lceil \frac{400}{32} \rceil = 13 32400=13 个块。
    因此,您的网格尺寸将是 29x13 个块,这确保了您有足够的线程块来为每个像素分配一个线程。需要注意的是,这将导致一些线程是多余的,因为29x32 = 928和13x32 = 416,而图像只有900x400。这意味着在宽度方向上将有28个线程和在高度方向上将有16个线程不会对应于图像中的任何像素。在kernel代码中,您需要添加适当的边界检查来避免这些线程进行越界操作。
    综上所述,您的内核配置应该如下:
  • 线程块尺寸(blockDim): (32, 32)
  • 网格尺寸(gridDim): (29, 13)
  1. 关于上一个问题,您希望有多少个空闲线程?

为了确定有多少个空闲线程,我们需要计算网格中所有线程的总数并减去图像中像素的总数。

我们已经决定使用一个网格尺寸为29x13的线程块,每个线程块的尺寸为32x32。所以,网格中总共的线程数是:

总线程数 = 网格宽度 × 网格高度 × 块宽度 × 块高度 \text{总线程数} = \text{网格宽度} \times \text{网格高度} \times \text{块宽度} \times \text{块高度} 总线程数=网格宽度×网格高度×块宽度×块高度

总线程数 = 29 × 13 × 32 × 32 \text{总线程数} = 29 \times 13 \times 32 \times 32 总线程数=29×13×32×32

总线程数 = 387 , 072 \text{总线程数} = 387,072 总线程数=387,072

图像中实际的像素总数是:

像素总数 = 图像宽度 × 图像高度 = 400 × 900 = 360 , 000 \text{像素总数} = \text{图像宽度} \times \text{图像高度} = 400 \times 900 = 360,000 像素总数=图像宽度×图像高度=400×900=360,000

因此,空闲线程的总数是:

空闲线程数 = 总线程数 − 像素总数 \text{空闲线程数} = \text{总线程数} - \text{像素总数} 空闲线程数=总线程数像素总数

空闲线程数 = 387 , 072 − 360 , 000 = 27 , 072 \text{空闲线程数} = 387,072 - 360,000 = 27,072 空闲线程数=387,072360,000=27,072

所以,将会有27,072个空闲线程。这些线程应该在kernel代码中通过边界检查来处理,以确保它们不会执行任何对应于图像外部的操作。

  1. 考虑一个假设的块,在到达block之前,有8个线程执行一段代码。线程需要以下时间(以微秒为单位)来执行这些部分:2.0、2.3、3.0、2.8、2.4、1.9、2.6和2.9,其余时间等待障碍。等待屏障的线程总执行时间的百分比是多少?
    答:在CUDA中,一个线程块中的所有线程在继续执行之前必须到达同步点(屏障)。这意味着所有线程必须等待直到块中最慢的线程完成其执行。在这个假设的情况下,最慢的线程需要3.0微秒来执行它的部分。

对于每个线程,等待时间是最慢线程的执行时间减去该线程的执行时间。我们需要计算每个线程的等待时间,然后将它们加起来得到总等待时间,最后计算这个总等待时间占所有线程执行时间总和的百分比。

让我们先计算总等待时间:

  • 线程1的等待时间: 3.0 − 2.0 = 1.0 3.0 - 2.0 = 1.0 3.02.0=1.0 微秒
  • 线程2的等待时间: 3.0 − 2.3 = 0.7 3.0 - 2.3 = 0.7 3.02.3=0.7 微秒
  • 线程3的等待时间: 3.0 − 3.0 = 0.0 3.0 - 3.0 = 0.0 3.03.0=0.0 微秒(最慢的线程,没有等待时间)
  • 线程4的等待时间: 3.0 − 2.8 = 0.2 3.0 - 2.8 = 0.2 3.02.8=0.2 微秒
  • 线程5的等待时间: 3.0 − 2.4 = 0.6 3.0 - 2.4 = 0.6 3.02.4=0.6 微秒
  • 线程6的等待时间: 3.0 − 1.9 = 1.1 3.0 - 1.9 = 1.1 3.01.9=1.1 微秒
  • 线程7的等待时间: 3.0 − 2.6 = 0.4 3.0 - 2.6 = 0.4 3.02.6=0.4 微秒
  • 线程8的等待时间: 3.0 − 2.9 = 0.1 3.0 - 2.9 = 0.1 3.02.9=0.1 微秒

总等待时间是所有线程等待时间的总和:

总等待时间 = 1.0 + 0.7 + 0.0 + 0.2 + 0.6 + 1.1 + 0.4 + 0.1 = 4.1  微秒 \text{总等待时间} = 1.0 + 0.7 + 0.0 + 0.2 + 0.6 + 1.1 + 0.4 + 0.1 = 4.1 \text{ 微秒} 总等待时间=1.0+0.7+0.0+0.2+0.6+1.1+0.4+0.1=4.1 微秒

总执行时间是所有线程执行时间的总和:

总执行时间 = 2.0 + 2.3 + 3.0 + 2.8 + 2.4 + 1.9 + 2.6 + 2.9 = 19.9  微秒 \text{总执行时间} = 2.0 + 2.3 + 3.0 + 2.8 + 2.4 + 1.9 + 2.6 + 2.9 = 19.9 \text{ 微秒} 总执行时间=2.0+2.3+3.0+2.8+2.4+1.9+2.6+2.9=19.9 微秒

等待时间占总执行时间的百分比是:

百分比 = ( 总等待时间 总执行时间 ) × 100 \text{百分比} = \left( \frac{\text{总等待时间}}{\text{总执行时间}} \right) \times 100 百分比=(总执行时间总等待时间)×100

百分比 = ( 4.1 19.9 ) × 100 ≈ 20.6 % \text{百分比} = \left( \frac{4.1}{19.9} \right) \times 100 \approx 20.6\% 百分比=(19.94.1)×10020.6%

因此,等待屏障的线程总执行时间的百分比大约是20.6%。

  1. 指出每个多处理器可以进行以下哪些分配。在不可能的情况下,请指出限制因素(s)。
    在这里插入图片描述
    好的,我们来看看每个多处理器可以进行的分配情况:

A. 在具有计算能力1.0的设备上,8个块,每个块128个线程

  • 计算能力1.0的设备每个多处理器的最大线程数为768,8个块乘以128个线程等于1024个线程,超出了最大线程数的限制。因此,这种分配是不可能的,限制因素是多处理器的最大线程数。

B. 在具有计算能力1.2的设备上,8个块,每个块128个线程

  • 计算能力1.2的设备每个多处理器的最大线程数为1024,8个块乘以128个线程等于1024个线程,没有超出限制。因此,这种分配是可能的。

C. 在具有计算能力3.0的设备上,8个块,每个块128个线程

  • 计算能力3.0的设备每个多处理器的最大线程数为2048,8个块乘以128个线程等于1024个线程,没有超出限制。因此,这种分配是可能的。

D. 在具有计算能力1.0的设备上,16个块,每个块64个线程

  • 计算能力1.0的设备每个多处理器的最大线程数为768,而16个块乘以64个线程等于1024个线程,超出了最大线程数的限制。此外,计算能力1.0的设备每个多处理器的最大块数为8,这里的16个块也超出了限制。因此,这种分配是不可能的,限制因素是多处理器的最大线程数和最大块数。

E. 在具有计算能力1.2的设备上,16个块,每个块64个线程

  • 计算能力1.2的设备每个多处理器的最大线程数为1024,而16个块乘以64个线程等于1024个线程,没有超出线程数限制。但是,计算能力1.2的设备每个多处理器的最大块数为8,这里的16个块超出了限制。因此,这种分配是不可能的,限制因素是多处理器的最大块数。

F. 在具有计算能力3.0的设备上,16个块,每个块64个线程

  • 计算能力3.0的设备每个多处理器的最大线程数为2048,而16个块乘以64个线程等于1024个线程,没有超出限制。计算能力3.0的设备每个多处理器的最大块数也足够容纳16个块。因此,这种分配是可能的。
  1. 一位CUDA程序员说,如果他们启动一个每个块中只有32个线程的内核,他们可以在需要障碍同步的地方省略__syncthreads()指令。你觉得这是个好主意吗?解释。
    答:不,这不是一个好主意。

__syncthreads()是CUDA编程中的一个同步屏障,它确保块内的所有线程在继续执行之前都达到这一点。这是为了避免竞争条件和数据不一致,尤其是当多个线程需要读写共享内存或者依赖于其他线程的计算结果时。

即使每个块中只有32个线程,也不能保证省略__syncthreads()指令不会导致问题。CUDA架构是SIMT(Single Instruction, Multiple Thread)架构,这意味着一组线程(称为一个线程束)将以锁步方式执行相同的指令。对于NVIDIA的CUDA架构,一个线程束通常包含32个线程,这也是所谓的warp的大小。

当一个块恰好等于一个warp的大小时,人们可能会认为每个warp内的线程是同时执行的,因此不需要同步。然而,这种假设是有风险的,因为:

  1. 即使在一个warp内部,线程执行的顺序和时间仍然是不确定的,尤其是当有分支指令时。
  2. 如果内核中的操作依赖于共享内存或全局内存的读写顺序,省略同步仍然可能导致错误的结果。
  3. 在未来的硬件或软件更新中,warp的行为可能会改变,这使得省略__syncthreads()可能会导致代码的可移植性和可维护性问题。

因此,除非代码的逻辑确保了不同线程之间绝对不需要同步(例如,每个线程使用独立的内存位置,且不依赖于其他线程的计算结果),否则省略__syncthreads()是不安全的。通常,最好是遵循标准的同步做法,以确保代码的正确性和健壮性。

  1. 一位学生提到,他能够通过使用32×32线程块的tile矩阵乘法代码来乘以两个1024×1024矩阵。他正在使用CUDA设备,每个块最多允许512个线程,每个SM最多允许8个块。他进一步提到,线程块中的每个线程都计算结果矩阵的一个元素。你会有什么反应,为什么?

答:
如果该学生声称他们使用32×32线程块来执行1024×1024矩阵的乘法,并且每个线程块中的每个线程都计算结果矩阵的一个元素,那么他们的配置与CUDA设备的硬件限制不符。具体来说,他们的线程块设置超过了每个块允许的最大线程数,因为32×32等于1024,而设备的限制是每个块最多512个线程。

这里的主要问题是,CUDA内核在执行时必须遵守硬件的限制。如果超出了这些限制,CUDA程序将无法成功执行,或者会得到错误的结果。由于CUDA内核的这个限制是由硬件决定的,因此程序员必须设计他们的线程块以适应这些限制。

因此,我的反应将是指出学生的配置错误,并建议他们重新设计线程块的尺寸。为了适应每个块最多512个线程的限制,他们可以选择如下配置之一:

  • 使用16×32线程块,每块有512个线程。
  • 使用32×16线程块,每块有512个线程。
  • 使用其他任何乘积不超过512的线程维度配置。

此外,由于每个SM允许最多8个块,这意味着在任何给定时刻,一个SM可以同时处理的块的数量有限。这个信息对于理解内核如何在多个SM上调度是有用的,但它并不影响线程块大小的选择,只要线程块的大小遵守了每个块的最大线程数限制。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/302373.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C语言详解之一维数组二维数组以及变长数组

一周新的开始&#xff0c;今天的你学习了吗&#xff1f; 前言 今天打算把数组的相关知识知识复习一下&#xff0c;比如初始化&#xff0c;调用&#xff0c;以及他和指针的关系等等 数组是什么 数组是一种数据结构&#xff0c;它由相同类型的元素组成&#xff0c;并按照一定的…

Spring学习 Spring AOP

4.Spring AOP 4.1.为什么要学习AOP? 案例&#xff1a;有一个接口Service有一个addUser方法&#xff0c;在调用addUser(被调用时打印调用前的毫秒数与调用后的毫秒数&#xff09;&#xff0c;其实现为&#xff1a; Service public class UserServiceImpl implements UserServi…

机器学习 前馈神经网络

人工神经网络&#xff08;Artificial Neural Network&#xff0c;ANN&#xff09;是指一系列受生物学和神经科学启发的数学模型&#xff0e;这些模型主要是通过对人脑的神经元网络进行抽象&#xff0c;构建人工神经元&#xff0c;并按照一定拓扑结构来建立人工神经元之间的连接…

【Vue3】2-5 : 指令系统与事件方法及传参处理

本书目录&#xff1a;点击进入 一、标签属性中的使用 - 指令系统 1.1 那么模板语法是否可以在标签属性中进行使用呢? ▶ 当然可以&#xff1a;使用 指令系统 二、指令系统 2.1 v-bind 2.2 v-on 三、实战 3.1 methods 选项 3.2 $event语法 一、标签属性中的使用 - 指令…

服务发现Discovery

对于注册进eureka里面的微服务&#xff0c;可以通过服务发现来获得该服务的信息 1、 修改cloud-provider-payment8001的controller import com.my.springcloud.utils.RestResponse; import com.my.springcloud.entities.Payment; import com.my.springcloud.service.PaymentSe…

文档审阅批注的合并和对比

#创作灵感# 最近在改论文&#xff0c;Feedback返回的时候&#xff0c;把之前的批注都删了&#xff0c;这就增加了工作量&#xff0c;看起来不方便&#xff0c;所以就需要将删掉的批注全部复原。 那在原来的文档重新在修改一遍&#xff0c;工作量还是很大的&#xff0c;所以这里…

java中的语法糖,你了解多少?

什么是语法糖 语法糖是一种编程语言的特性&#xff0c;通常是一些简单的语法结构或函数调用&#xff0c;它可以通过隐藏底层的复杂性&#xff0c;并提供更高级别的抽象&#xff0c;从而使代码更加简洁、易读和易于理解。但它并不会改变代码的执行方式。 语法糖优势 1. 简化代…

Turn.js 实现翻书效果

接到了任务&#xff0c;要把孩子画的画放到网页上去&#xff0c;翻页效果还要逼真一点。搜索到了turn.js这个前端翻页组件&#xff0c;效果不错。先上图看效果。 网页实际效果&#xff1a;星月夜诗集 turn.js的官网地址&#xff1a;Turn.js: The page flip effect in HTML5 …

内存映射-进程通信

内存映射(mmap) 1. 创建内存映射区 实现进程间通信&#xff0c;还可以通过函数创建一块内存映射区&#xff0c;和管道不同的是管道对应的内存空间在内核中&#xff0c;而内存映射区对应的内存空间在进程的用户区&#xff08;用于加载动态库的那个区域&#xff09;&#xff0c…

1.4号io网络

1.多进程 引入目的&#xff1a;让多个任务实现并发执行 并发执行&#xff1a;同一时间只有一个进程执行&#xff0c;通过时间轮询调度多个进程&#xff0c;由于时间每个进程所用时间极短&#xff0c;所以宏观表现为多个进程同时进行。 并行执行&#xff1a;多个任务器执行多…

【Python】Graphviz的安装和使用

graphviz包可以用来决策树可视化&#xff0c;只安装包之后直接import使用会报错&#xff0c;因为graphviz是一个要单独安装的软件。 下载路径&#xff1a;Download | Graphviz 有不同的版本&#xff0c;我这里用的是最新版 9.0版本安装之后可以选自动添加到环境变量——系统…

LeetCode刷题12:贪心算法解决1402.做菜顺序

一个厨师收集了他 n 道菜的满意程度 satisfaction &#xff0c;这个厨师做出每道菜的时间都是 1 单位时间。 一道菜的 「 like-time 系数 」定义为烹饪这道菜结束的时间&#xff08;包含之前每道菜所花费的时间&#xff09;乘以这道菜的满意程度&#xff0c;也就是 time[i]*sa…

[De1ctf 2019]SSRF Me

目录 具体做题分析&#xff1a; 字符串拼接&#xff1a; 哈希拓展攻击&#xff1a; 点开是一段flask代码&#xff0c;经过还原后格式如下&#xff1a; #!/usr/bin/env python# encodingutf-8from flask import Flask, requestimport socketimport hashlibimport urllibimpo…

pod节点jar包替换流程

1、查找到该docker容器 docker ps | grep backend # ./entrypoint.sh文件启动的那个容器2、替换jar 包 mv xxx.jar app.jar docker cp app.jar 66bc6fea9fb5:/home/aimind/3、重启容器 docker restart 66bc6fea9fb5 4、重启容器后进行功能验证 功能验证没问题了&#xff0c;再…

决策树--CART回归树算法详解

1、介绍 &#xff08;1&#xff09;简介 CART&#xff08;Classification and Regression Trees&#xff09;回归树是一种基于决策树的机器学习算法&#xff0c;用于预 测连续型目标变量而不是离散型类别变量。 &#xff08;2&#xff09;生成过程 ① 选择一个特征和相应的…

在win10上cuda12+tensorrt8.6+vs2019环境下编译paddle2.6生成python包与c++推理库

paddle infer官方目前没有发布基于cuda12的c库&#xff0c;为此参考https://www.paddlepaddle.org.cn/inference/user_guides/source_compile.html实现cuda12的编译安装&#xff0c;不料博主才边缘好自己的paddle2.6&#xff0c;paddle官方已经发布了cuda12.0的paddle2.6框架。…

全视通发表“物联网赋能智慧医院建设”主题演讲获关注

邕州山河&#xff0c;神州沃壤。近日&#xff0c;备受瞩目的“2024广西医院和实验室建设学术年会暨净化专业委员会成立六周年庆典”在广西南宁圆满召开。作为智慧医康养整体方案提供商&#xff0c;全视通受邀参会并发表了主题为“物联网赋能智慧医院建设”的演讲&#xff0c;深…

1873_ssh scp的速度限制设置

全部学习汇总&#xff1a; GreyZhang/little_bits_of_linux: My notes on the trip of learning linux. (github.com) 正常情况下&#xff0c;我们对于传输速度的要求自然是越快越好。不过凡事也有一个例外&#xff0c;比如我遇到的一个场景&#xff1a;经过了内网穿透的环境&a…

Web前端篇——ElementUI之el-scrollbar + el-backtop + el-timeline实现时间轴触底刷新和一键返回页面顶部

ElementUI之el-scrollbar el-backtop el-timeline实现时间轴触底刷新和一键返回页面顶部。 背景&#xff1a;ElementUI的版本&#xff08;vue.global.js 3.2.36&#xff0c; index.css 2.4.4&#xff0c; index.full.js 2.4.4&#xff09; 废话不多说&#xff0c;先看动…

卷积神经网络|猫狗分类系列--导入kaggle猫狗数据集

解决任何真实问题的重要一步是获取数据&#xff0c;Kaggle提供了大量不同数据科学问题的竞赛。 我们将从 https://www.kaggle.com/competitions/dogs-vs-cats/data 下载猫狗数据集&#xff0c;并对其进行一定的操作&#xff0c;以正确的导入到我们的计算机&#xff0c;为接下…