前言

  本文是个人学习心得的分享,希望大家在阅读文章后能在评论中一起学习交流!另外还可以访问我的HelloCUDA仓库查看我在学习CUDA中写的一些demo程序。

内容概要

  • 复数的CUDA C++实现
  • 从DFT到FFT
  • FFT蝴蝶操作
  • CUDA中的分治
  • FFT的并行化

前置知识

  • 算法基础知识
  • 并行计算基础知识
  • C++基础知识
  • CUDA编程基础
  • 离散傅里叶变换的原理

从DFT到FFT

  离散傅里叶变化(Discrete Fourier Transform)是傅里叶变换的简化版本,计算机科学家发明出离散傅里叶变换目的就是要让具有连续性质的傅里叶变换能在具有离散性质的计算机中被应用。而离散傅里叶变换算法时间复杂度高(O(n2)O(n^2)),使其在大规模场景中的应用受到限制,从而诞生了快速傅里叶变换(Fast Fourier Transform).
快速傅里叶变换的实现采用的是分治的思想。利用DFT的数学性质可以将一个DFT分解为多个DFT。数列a0,a1,a2,...,ana_0, a_1, a_2, ..., a_n的离散傅里叶变换的本质是求多项式A(x)=a0+a1x+a2x2+...+anxn1A(x) = a_0 + a_1x + a_2x^2 + ... + a_nx^{n-1}nn次单位复根处的取值,变换后的数列为A(wn0),A(wn1),A(wn2),...,A(wnn1)A(w_n^0), A(w_n^1), A(w_n^2), ..., A(w_n^{n-1})。其中wni,i=0,1,...,n1w_n^i, i=0, 1, ..., n-1是方程wn=1w^n = 1nn个根 (此处有疑惑请参考离散傅里叶变换的原理). 因此,对于长度为nn的数列进行DFT共需要进行nn次多项式求值,每次求值的复杂度为O(n)O(n),因此总体时间复杂度为O(n2)O(n^2).
了解从DFT到FFT原理的读者可以跳过以下三段内容。将上述多项式A(x)A(x)按照下标为奇数或偶数分解为两个多项式A0(x)=a0+a2x+a4x2+a6x4+...A_0(x)=a_0 + a_2x + a_4x^2 + a_6x^4 + ...A1(x)=a1+a3x+a5x2+a7x3+...A_1(x) = a_1 + a_3x + a_5x^2 + a_7x^3 + .... 可知A(x)=A0(x2)+xA1(x2)A(x)=A_0(x^2) + xA_1(x^2). 而A0A_0A1A_1又可继续分解,形成一个递归的分解过程。由折半引理(wn2=wn/2w_n^2 = w_{n/2})可知,A(wnk)=A0(wn/2k)+wnkA1(wn/2k)A(w_n^k) = A_0(w_{n/2}^k) + w_n^kA_1(w_{n/2}^k). 因此,求原数列的DFT问题被分解为偶数下标子序列的DFT和奇数下标子序列的DFT。
n=8n=8为例,将a0a_0a7a_7分解为两个子数列a0,a2,a4,a6a_0, a_2, a_4, a_6a1,a3,a5,a7a_1, a_3, a_5, a_7,则满足A(w8k)=A0(w4k)+w8kA1(w4k)A(w_8^k) = A_0(w_4^k) + w_8^kA_1(w_4^k),两个子数列的DFT分别为A0(w40),A0(w41),A0(w42),A0(w43)A_0(w_4^0), A_0(w_4^1), A_0(w_4^2), A_0(w_4^3)A1(w40),A1(w41),A1(w42),A1(w43)A_1(w_4^0), A_1(w_4^1), A_1(w_4^2), A_1(w_4^3). 原数列DFT的第1项为:
A(w80)=A0(w40)+w80A1(w40) A(w_8^0)=A_0(w_4^0) + w_8^0A_1(w_4^0)
奇数下标子数列的第1项 + w80w_8^0 * 偶数下标子数列的第1项。值得注意的是,与子数列第1项有关的不只有原数列DFT的第1项,还有第5项。特别注意下面出现的这个等式,原数列的DFT的第5项为(注意kk是从0开始的,这里k=4k=4):
A(w84)=A0(w44)+w84A1(w44)=A0(w40)w80A1(w40) A(w_8^4)=A_0(w_4^4) + w_8^4A_1(w_4^4)=A_0(w_4^0)-w_8^0A_1(w_4^0)
奇数下标子数列的第1项 - w80w_8^0 * 偶数下标子数列的第1项,就是把前面的加变成了减。同理不难得出原数列DFT的第2项和第6项第3项和第7项第4项和第8项都满足这个规则。
上述过程是建立在子数列的DFT已经求出来的假设下进行分析的,实际上还需要求解子数列的DFT才能进行原数列DFT的求解,这显然是一个分治的过程,如下图所示:
分解过程
最终分解为求长度为1的数列的DFT. 数列a0a_0和数列a4a_4的DFT分别是它们本身,因此它们的父序列a0,a4a_0, a_4的DFT为a0+w10a4,a0w10a4a_0 + w_1^0a_4, a_0 - w_1^0a_4,这个DFT的结果需要继续提供给a0,a4a_0, a_4的父序列使用,层层向上,如此进行递归。计算机科学家引入蝴蝶操作来描述这一过程。一个蝴蝶操作的输入是两个数,输出也是两个数,其本身还拥有一个叫旋转因子,结构如下图所示:
蝴蝶操作
其中输入来自两个子数列相同位置kk的两个数,旋转因子中的nn等于原数列长度,即两个子数列长度之和。蝴蝶操作的输出可以继续作为后续蝴蝶操作的输入,用来处理上面过程所述的层层向上的过程。最终得到如下过程:(注意与分解过程的图进行对照,检验该图中进行蝴蝶操作的两个数是否来自子数列的同一位置,这样能更好地理解整个过程)
递归蝴蝶操作

蝴蝶操作并行化

  分治过程分为分解和合并阶段,蝴蝶操作是在合并阶段进行的。第1组合并是对长度为1的数列进行两两合并,共需做n/2n/2次合并,每次合并需要1次蝴蝶操作,该组合并共进行了n/2n/2次蝴蝶操作。以此类推可知,每一组合并都需要进行n/2n/2次蝴蝶操作,共进行log2nlog_2n组合并,因此时间复杂度为O(nlog2n)O(nlog_2n).
不难看出,每组合并过程内的所有蝴蝶操作是可以同时进行的,因为它们在图中没有先后顺序关系。若分配n/2n/2个线程同时处理每一组合并中的n/2n/2次蝴蝶操作,则每一组合并的并行时间复杂度为O(1)O(1),共进行log2nlog_2n组合并,最终的并行时间复杂度为O(log2n)O(log_2n).

CUDA C++实现

前置工作:复数的C++实现

  C++自带的库无法在device上运行,因此需要自己实现复数数据结构并同时提供host和device的函数。作者在自己实现复数时加入了生成nn次单位复根的功能。实现复数最主要的是要实现运算符重载,即复数的加、减、乘,原理较简单,若想深究请自行查找资料。另外,本文中数列的数值都用复数数据结构来存储,如为实数则将虚部存为0,而不是直接使用浮点数存储。以下给出复数实现的代码,注意__device__标记

class Complex {
public:
    double real;
    double imag;    Complex() {    }    // Wn 获取n次单位复根中的主单位根
    __device__ static Complex W(int n) {
        Complex res = Complex(cos(2.0 * PI / n), sin(2.0 * PI / n));
        return res;
    }    // Wn^k 获取n次单位复根中的第k个
    __device__ static Complex W(int n, int k) {
        Complex res = Complex(cos(2.0 * PI * k / n), sin(2.0 * PI * k / n));
        return res;
    }
    
    // 实例化并返回一个复数(只能在Host调用)
    static Complex GetComplex(double real, double imag) {
        Complex r;
        r.real = real;
        r.imag = imag;
        return r;
    }    // 随机返回一个复数
    static Complex GetRandomComplex() {
        Complex r;
        r.real = (double)rand() / rand();
        r.imag = (double)rand() / rand();
        return r;
    }    // 随即返回一个实数
    static Complex GetRandomReal() {
        Complex r;
        r.real = (double)rand() / rand();
        r.imag = 0;
        return r;
    }    // 随即返回一个纯虚数
    static Complex GetRandomPureImag() {
        Complex r;
        r.real = 0;
        r.imag = (double)rand() / rand();
        return r;
    }    // 构造函数(只能在Device上调用)
    __device__ Complex(double real, double imag) {
        this->real = real;
        this->imag = imag;
    }
    
    // 运算符重载
    __device__ Complex operator+(const Complex &other) {
        Complex res(this->real + other.real, this->imag + other.imag);
        return res;
    }    __device__ Complex operator-(const Complex &other) {
        Complex res(this->real - other.real, this->imag - other.imag);
        return res;
    }    __device__ Complex operator*(const Complex &other) {
        Complex res(this->real * other.real - this->imag * other.imag, this->imag * other.real + this->real * other.imag);
        return res;
    }
};

分治的并行实现

  在使用串行化的方法实现分治时,可以借助递归进行问题的分解。然而CUDA是基于内存共享的并行计算框架,递归不利于程序的并行化,因此需要使用循环代替递归。

__global__ void Reduce(int nums[], int n) {
    int tid = threadIdx.x + blockDim.x * blockIdx.x;  // 线程号, 每个数对应一个线程
    if (tid >= n) return;  // 线程号超出数列范围, 返回
    for (int i = 2; i < 2 * n; i *= 2) {
        if (tid % i == 0) {
            nums[tid] += nums[tid + i / 2];  // 基本代码
        }
        __syncthreads();  // 同步线程
    }
}

  上述代码展示的是使用分治法进行数列求和的过程,最终的运行结果是数列的和被求出并存储在nums[0]中。对每次循环进行分析。第一次循环中,能进入基本代码的进程的tid为0, 2, 4, 6, …,本次循环执行完基本代码后,nums中1, 3, 5, 7, … 位置上的数都被加到了0, 2, 4, 6, … 位置上。第二次循环中,能进入基本代码的进程的tid为0, 4, 8, 12, …,本次循环执行完成后,nums中2, 6, 10, 14, … 位置上的数(存储的是第一次相加的结果)都被加到了0, 4, 8, 12, …  位置上。往后的循环都同理,其中最后一次循环,只有tid为0的进程能进入基本代码,将nums[n/2]加到nums[0]上,完成所有数的求和。

FFT分治面临的问题

  FFT分治的最大问题在于每次合并的两项并不来自相邻的进程。以n=8n=8为例,在数列求和问题中,第一次循环进行合并操作的两项分别为:0和1、2和3、4和5、6和7,但在FFT中,第一次循环进行合并操作的两项分别为:0和4、2和6、1和5、3和7. 往后的循环同样存在这个问题。解决方案是将数列按照0, 4, 2, 6, 1, 5, 3, 7的顺序重新排序。
那么0, 4, 2, 6, 1, 5, 3, 7和原数列之间有什么关系呢?该数列的二进制数列为000, 100, 010, 110, 001, 101, 011, 111,将每个二进制数逆转,得到数列000, 001, 010, 011, 100, 101, 110, 111即原数列0, 1, 2, 3, 4, 5, 6, 7. 引入二进制逆转操作,对原数列重新排序可解决此问题。以下给出一个完整的程序来解释其C++实现:

// 根据数列长度n计算二进制最高位数
int GetBits(int n) {
    int bits = 0;
    while (n >>= 1) {
        bits++;
    }
    return bits;
}// 在二进制位数为bits的前提下求数值i的二进制逆转
int BinaryReverse(int i, int bits) {
    int r = 0;
    do {
        r += i % 2 << --bits;
    } while (i /= 2);
    return r;
}int main() {
    const int n = 8;
    const int bits = GetBits(n);
    int nums[n] = { 3, 8, 2, 4, 1, 6, 7, 9 };
    int j = BinaryReverse(1, bits);  // 排序后的数列的第1个位置对应原数列中的第j个位置
    printf("排序后的数列第1个位置上的数为%d", nums[j]);
}

各线程蝴蝶操作的时机

  设计CUDA程序需要明确数据在kernel中的位置,以及每个线程执行操作的时机,有时还需要考虑线程之间的同步。
前面已经讲述了并行分治的每次循环分别有哪些进程可以进入基本代码。以n=8n=8为例,用以下表格对比数列求和FFT操作的第一次循环中需要进行合并操作的两项:

线程 数列求和操作 FFT操作
0 nums[0]nums[1] nums[BinaryReverse(0)]nums[BinaryReverse(1)]
2 nums[2]nums[3] nums[BinaryReverse(2)]nums[BinaryReverse(3)]
4 nums[4]nums[5] nums[BinaryReverse(4)]nums[BinaryReverse(5)]
6 nums[6]nums[7] nums[BinaryReverse(6)]nums[BinaryReverse(7)]
tid nums[tid]nums[tid+1] nums[BinaryReverse(tid)]nums[BinaryReverse(tid+1)]

通过对比第一次循环可以看出,定义了BinaryReverse操作之后,确认合并对象在数列中的位置这个问题已经解决,只需用BinaryReverse(tid)替代tid即可确认数的位置。
数列求和每次合并操作合并的是两个数,但FFT每次合并操作合并的都是两个数列。为了便于理解,仍然以n=8n=8为例,用以下表格对比数列求和FFT操作的第二次和第三次循环中需要进行合并操作的两项:

线程 数列求和操作 FFT操作
0 nums[0]nums[2] 1. nums[BinaryReverse(0)]nums[BinaryReverse(2)]
2. nums[BinaryReverse(1)]nums[BinaryReverse(3)]
4 nums[4]nums[6] 1. nums[BinaryReverse(4)]nums[BinaryReverse(6)]
2. nums[BinaryReverse(5)]nums[BinaryReverse(7)]
tid nums[tid]nums[tid+2] 1. nums[BinaryReverse(tid)]nums[BinaryReverse(tid+2)]
2. nums[BinaryReverse(tid+1)]nums[BinaryReverse(tid+3)]
线程 数列求和操作 FFT操作
0 nums[0]nums[4] 1. nums[BinaryReverse(0)]nums[BinaryReverse(4)]
2. nums[BinaryReverse(1)]nums[BinaryReverse(5)]
3. nums[BinaryReverse(2)]nums[BinaryReverse(6)]
4. nums[BinaryReverse(3)]nums[BinaryReverse(7)]
tid nums[tid]nums[tid+4] 1. nums[BinaryReverse(tid)]nums[BinaryReverse(tid+4)]
2. nums[BinaryReverse(tid+1)]nums[BinaryReverse(tid+5)]
3. nums[BinaryReverse(tid + 2)]nums[BinaryReverse(tid+6)]
4. nums[BinaryReverse(tid + 3)]nums[BinaryReverse(tid+7)]

通过以上对比可以看出,在FFT操作中,tid和tid+2 (或tid+4) 的作用是进行定位,找到需要合并的两个数列的开头。在本文第一份代码的基础上引入一层内部循环,可以达到这个要求:

// 蝴蝶操作, 输出结果直接覆盖原存储单元的数据, factor是旋转因子
__device__ void Bufferfly(Complex *a, Complex *b, Complex factor) {
    Complex a1 = (*a) + factor * (*b);
    Complex b1 = (*a) - factor * (*b);
    *a = a1;
    *b = b1;
}__global__ void FFT(Complex nums[], int n, int bits) {
    int tid = threadIdx.x + blockDim.x * blockIdx.x;
    if (tid >= n) return; 
    for (int i = 2; i < 2 * n; i *= 2) {
        if (tid % i == 0) {
            // 新引入的循环
            for (int j = 0; j < k / 2; ++j) {
                Bufferfly(&nums[BinaryReverse(tid + j, bits)], &nums[BinaryReverse(tid + j + k / 2, bits)], Complex::W(k, j));
            }
        }
        __syncthreads();
    }
}

上述代码已经完成了FFT运算,但FFT结果数列的顺序是按照逆转二进制数的顺序排列的,因此在拷贝结果时应按逆转二进制数的顺序来拷贝。为此,引入一个数组result来存储最终结果:

__global__ void FFT(Complex nums[], Complex result[], int n, int bits) {
    int tid = threadIdx.x + blockDim.x * blockIdx.x;
    if (tid >= n) return;
    for (int i = 2; i < 2 * n; i *= 2) {
        if (tid % i == 0) {
            for (int j = 0; j < k / 2; ++j) {
                Bufferfly(&nums[BinaryReverse(tid + j, bits)], &nums[BinaryReverse(tid + j + k / 2, bits)], Complex::W(k, j));
            }
        }
        __syncthreads(); 
    }
    result[tid] = nums[BinaryReverse(tid, bits)];  // 拷贝到result中的对应地址
}

完整代码

// 一维FFT
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include "../utils/Complex.cu"  // 自定义的复数数据结构
#include <iostream>
#include <string>
#include <stdlib.h>
#include <time.h>
#include <Windows.h>// 根据数列长度n获取二进制位数
int GetBits(int n) {
    int bits = 0;
    while (n >>= 1) {
        bits++;
    }
    return bits;
}// 在二进制位数为bits的前提下求数值i的二进制逆转
__device__ int BinaryReverse(int i, int bits) {
    int r = 0;
    do {
        r += i % 2 << --bits;
    } while (i /= 2);
    return r;
}// 蝴蝶操作, 输出结果直接覆盖原存储单元的数据, factor是旋转因子
__device__ void Bufferfly(Complex *a, Complex *b, Complex factor) {
    Complex a1 = (*a) + factor * (*b);
    Complex b1 = (*a) - factor * (*b);
    *a = a1;
    *b = b1;
}__global__ void FFT(Complex nums[], Complex result[], int n, int bits) {
    int tid = threadIdx.x + blockDim.x * blockIdx.x;
    if (tid >= n) return;
    for (int i = 2; i < 2 * n; i *= 2) {
        if (tid % i == 0) {
            int k = i;
            if (n - tid < k) k = n - tid;
            for (int j = 0; j < k / 2; ++j) {
                Bufferfly(&nums[BinaryReverse(tid + j, bits)], &nums[BinaryReverse(tid + j + k / 2, bits)], Complex::W(k, j));
            }
        }
        __syncthreads();
    }
    result[tid] = nums[BinaryReverse(tid, bits)];
}// 打印数列
void printSequence(Complex nums[], const int N) {
    printf("[");
    for (int i = 0; i < N; ++i) {
        double real = nums[i].real, imag = nums[i].imag;
        if (imag == 0) printf("%.16f", real);
        else {
            if (imag > 0) printf("%.16f+%.16fi", real, imag);
            else printf("%.16f%.16fi", real, imag);
        }
        if (i != N - 1) printf(", ");
    }
    printf("]\n");
}int main() {
    srand(time(0));  // 设置随机数种子
    const int TPB = 1024;  // 每个Block的线程数,即blockDim.x
    const int N = 1024 * 32;  // 数列大小
    const int bits = GetBits(N);
    
    // 随机生成实数数列
    Complex *nums = (Complex*)malloc(sizeof(Complex) * N), *dNums, *dResult;
    for (int i = 0; i < N; ++i) {
        nums[i] = Complex::GetRandomReal();
    }
    printf("Length of Sequence: %d\n", N);
    // printf("Before FFT: \n");
    // printSequence(nums, N);
    
    // 保存开始时间
    float s = GetTickCount();
    
    // 分配device内存,拷贝数据到device
    cudaMalloc((void**)&dNums, sizeof(Complex) * N);
    cudaMalloc((void**)&dResult, sizeof(Complex) * N);
    cudaMemcpy(dNums, nums, sizeof(Complex) * N, cudaMemcpyHostToDevice);
    
    // 调用kernel
    dim3 threadPerBlock = dim3(TPB);
    dim3 blockNum = dim3((N + threadPerBlock.x - 1) / threadPerBlock.x);
    FFT<<<blockNum, threadPerBlock>>>(dNums, dResult, N, bits);    // 拷贝回结果
    cudaMemcpy(nums, dResult, sizeof(Complex) * N, cudaMemcpyDeviceToHost);
    
    // 计算用时
    float cost = GetTickCount() - s;
    // printf("After FFT: \n");
    // printSequence(nums, N);
    printf("Time of Transfromation: %fms", cost);
  
    // 释放内存
    free(nums);
    cudaFree(dNums);
    cudaFree(dResult);
}
查看全文
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

相关文章

  1. 微信官方canvas wxml-to-canvas使用,并结合weapp-qrcode,画二维码,合成一张图,并下载

    wxml-to-canvas weapp-qrcode.js demo地址 附带,其他大佬的解决方案。...

    2024/4/17 8:46:08
  2. 【网络】HTTPS理论基础

    转载地址: HTTPS理论基础 HTTPS的4次握手是指SSL认证+TCP的3次握手吗?...

    2024/4/15 4:23:33
  3. 根据两个日期返回天数差

    /** * 根据两个日期返回天数差 * @return String */ public static long getDifferDay(String time1) { try { long time = 0l;String time2 = new SimpleDateFormat("yyyy-MM-dd").format(new Date());//time2:当前日期long t1 = new SimpleDateFormat("yyyy-M…...

    2024/4/21 22:21:00
  4. 超详细推导八大排序之插入排序

    插入排序思路:首先把一组数据分成两个部分,一部分是已经排好顺序的,这里我按照从小到大排列(这部分记作A),一部分是待排列数据(这部分记作B),默认排列好的部分只有一个数据也就是arr[0],然后将后面的数据依次与arr[0]比较,如果小于arr[0]则需要插入到arr[0]的前面(因…...

    2024/4/29 21:42:56
  5. 6.11 C语言练习([C语言训练]计算t=1+1/2+1/3+...+1/n)

    【练习】 题目要求:[C语言训练]计算t=1+1/2+1/3+...+1/n#include<stdio.h> int main() {int N;double i,sum;scanf("%d",&N);for(i=1.0;i<=N;i++){sum+= (1/i);}printf("%.6lf",sum);return 0; }...

    2024/4/24 12:47:20
  6. Spark1.x升级Spark2.x常见异常HBase篇【hbase.rpc.timeout】

    一.场景分析 大数据环境频繁使用metastore连接HBase加载数据时,偶尔会抛出hbase.rpc.timeout异常导致任务直接失败的情况。 异常信息: Caused by: org.apache.hadoop.hbase.ipc.CallTimeoutException: Call id=2, waitTime=600020, operationTimeout=600000 expired.at org.a…...

    2024/4/28 16:17:13
  7. Android ImageView图片点击时放大,松开时恢复原来的状态

    前言 最近在开发中,遇到点击ImagView时要求放大,然后松开后恢复原来的状态,这时就需要setOnTouchEvent的事件,然后处理 MotionEvent.ACTION_DOWN和MotionEvent.ACTION_UP事件就可以了 MotionEvent.ACTION_DOWN时图片放大,MotionEvent.ACTION_UP恢复原来的样子 具体代码如下…...

    2024/4/28 8:20:25
  8. 实现简单的斗地主发牌

    //斗地主的步骤:创建编号和牌对对应的map集合,准备牌,洗牌,发牌,排序,从map集合查找,看牌 public class Demo_test {public static void main(String[] args) {//创建编号和牌对应的map集合Map<Integer, String> map = new LinkedHashMap<Integer, String>(…...

    2024/4/30 19:38:00
  9. Windows10 Docker安装最新版本Redmine(4.1.1)+MySQL(8)

    Windows10 Docker安装最新版本Redmine(4.1.1)+MySQL(8) 最近需要安装redmine,在网上找了一些教程,但是都是使用redmine 4.0.4 和 mysql 5.7,感觉有点旧,于是自己写个最新版本的手顺记录一下踩过的坑。 Step1:拉取redmine和mysql最新镜像 命令: docker pull redmine docke…...

    2024/4/24 12:47:16
  10. Guessing Camels

    题目链接:Guessing Camels把每个数字在分别三个数组出现的位置当成三个维度的下标。 那么问题就变成一个三维偏序了,cdq分治即可。AC代码: #pragma GCC optimize("-Ofast","-funroll-all-loops") #include<bits/stdc++.h> //#define int long lon…...

    2024/4/24 12:47:15
  11. 对称二叉树(C++实现)

    给定一个二叉树,检查它是否是镜像对称的。 例如,二叉树 [1,2,2,3,4,4,3] 是对称的。1/ \2 2/ \ / \3 4 4 3但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的:1/ \2 2\ \3 3<方法1>递归实现 #include<iostream> #include<queue> using name…...

    2024/4/24 12:47:14
  12. Shell脚本实现自动登录服务器

    1.登录脚本 login_server.sh #!/bin/bash# ReferenceLink:https://yq.aliyun.com/articles/516347#show all host infos of serverList.txtif [[ -f ./serverList.txt ]] thenhostNum=`cat ./serverList.txt | wc -l` elseecho "No .serverList.txt in ./ dir, please cr…...

    2024/4/24 12:47:13
  13. 模式识别作业6

    模式识别作业6 clear;clc; tune_b = 28; % 需要调的参数1 tune_T = 0; % 需要调的参数2 A = [];N1=9; % 每个数字样本个数为N1+1,需要调的参数3 N = 10*(N1+1); % 样本总数为N for i=0:9B = [];for j=0:N1x = im2double(imread(strcat(D:\kp_matlab\hw6-number_recog\01\imag…...

    2024/4/24 12:47:15
  14. Vue之v-if指令与v-show指令

    一 App组件<template><section><mongo :key="1" v-if="show"/><mongo :key="2" v-show="show"/></section> </template> <script> import Mongo from "./mongo";export default …...

    2024/4/24 12:47:11
  15. ForkJoinPool线程池原理分析

    一、引言算法领域有一种基本思想叫做“分治”,所谓“分治”就是将一个难以直接解决的大问题,分割成一些规模较小的子问题,以便各个击破,分而治之。比如:对于一个规模为N的问题,若该问题可以容易地解决,则直接解决;否则将其分解为K个规模较小的子问题,这些子问题互相独…...

    2024/4/24 12:47:13
  16. Qt:QSqlTableModel 设置不同角色数据的方法

    QSqlTableModel是用于从单个表读写数据库记录的高级接口。它构建在底层的QSqlQuery之上,可用于为视图类(比如QTableView)提供数据。例如:QSqlTableModel *model = new QSqlTableModel;model->setTable("employee");model->setEditStrategy(QSqlTableModel::On…...

    2024/4/24 12:47:10
  17. 前端每日一题:手写async await的最简实现(20行搞定)!阿里字节面试必考

    手写async await的最简实现(20行搞定)!阿里字节面试必考 前言 如果让你手写async函数的实现,你是不是会觉得很复杂?这篇文章带你用20行搞定它的核心。 经常有人说async函数是generator函数的语法糖,那么到底是怎么样一个糖呢?让我们来一层层的剥开它的糖衣。 有的同学想…...

    2024/4/24 12:47:08
  18. sql server 数据库面试中遇到的坑

    最近面试发现了一个规律,那就是招聘岗位级别越高的越是注重面试者的基础知识; 比如以下问题,明明开发中经常使用的东西,换了一种问法就不知道是什么了; 1.分别说说 内连接,外连接,交叉连接,笛卡尔积 是什么? 看见题目的第一反应是脑袋顶上出现三个 “???” ,我只知…...

    2024/4/24 12:47:07
  19. 双机调试 WinDbg调试VMware虚拟机Windows7及更高版本(详细流程)

    一、关闭win7(或更高版本)虚拟机,更改配置。 注意这里要将虚拟机关闭,挂起时无法更改配置。 按照图示添加一个串行端口 接下来按照图示设置所创建的串行端口配置二、打开虚拟机,修改配置 以管理员身份运行CMD,执行以下命令: bcdedit /dbgsettings serial baudrate:115200 …...

    2024/4/24 12:47:06
  20. 秒杀系统Web实践——04压力测试(性能测试JMeter)

    第四章秒杀压测目录第四章秒杀压测1.SpringBoot打包1.1SpringBoot打jar包1.2SpringBoot打war包2.JMeter2.1Windows下使用2.2命令行下使用3.自定义变量模式多用户4.Redis压测工具redis-benchmark综述1.SpringBoot打包1.1SpringBoot打jar包注意把packaging标签改为jar,此标签也可…...

    2024/4/15 4:23:41

最新文章

  1. 深度学习中的变形金刚——transformer

    很荣幸能和这些大牛共处一个时代。网络结构名字可以是一个卡通形象——变形金刚&#xff0c;论文名字可以来源于一首歌——披头士乐队的歌曲《All You Need Is Love》。 transformer在NeurIPS2017诞生&#xff0c;用于英语-德语&#xff0c;英语-法语的翻译&#xff0c;在BLEU…...

    2024/5/1 5:20:10
  2. 梯度消失和梯度爆炸的一些处理方法

    在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言&#xff0c;在此感激不尽。 权重和梯度的更新公式如下&#xff1a; w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...

    2024/3/20 10:50:27
  3. 【VTKExamples::Meshes】第七期 TableBasedClipDataSetWithPolyData

    很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403 公众号:VTK忠粉 前言 本文分享VTK样例TableBasedClipDataSetWithPolyData,并解析接口vtkTableBasedClipDataSet,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你…...

    2024/4/30 9:11:58
  4. 【图论】知识点集合

    边的类型 neighbors(邻居)&#xff1a;两个顶点有一条共同边 loop&#xff1a;链接自身 link&#xff1a;两个顶点有一条边 parallel edges&#xff1a;两个顶点有两条及以上条边 无向图 必要条件&#xff1a;删掉顶点数一定大于等于剩下的顶点数 设无向图G<V,E>是…...

    2024/4/30 5:29:00
  5. 【外汇早评】美通胀数据走低,美元调整

    原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...

    2024/4/29 23:16:47
  6. 【原油贵金属周评】原油多头拥挤,价格调整

    原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...

    2024/4/30 18:14:14
  7. 【外汇周评】靓丽非农不及疲软通胀影响

    原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...

    2024/4/29 2:29:43
  8. 【原油贵金属早评】库存继续增加,油价收跌

    原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...

    2024/4/30 18:21:48
  9. 【外汇早评】日本央行会议纪要不改日元强势

    原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...

    2024/4/27 17:58:04
  10. 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响

    原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...

    2024/4/27 14:22:49
  11. 【外汇早评】美欲与伊朗重谈协议

    原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...

    2024/4/28 1:28:33
  12. 【原油贵金属早评】波动率飙升,市场情绪动荡

    原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...

    2024/4/30 9:43:09
  13. 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试

    原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...

    2024/4/27 17:59:30
  14. 【原油贵金属早评】市场情绪继续恶化,黄金上破

    原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...

    2024/4/25 18:39:16
  15. 【外汇早评】美伊僵持,风险情绪继续升温

    原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...

    2024/4/28 1:34:08
  16. 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势

    原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...

    2024/4/26 19:03:37
  17. 氧生福地 玩美北湖(上)——为时光守候两千年

    原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...

    2024/4/29 20:46:55
  18. 氧生福地 玩美北湖(中)——永春梯田里的美与鲜

    原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...

    2024/4/30 22:21:04
  19. 氧生福地 玩美北湖(下)——奔跑吧骚年!

    原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...

    2024/5/1 4:32:01
  20. 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!

    原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...

    2024/4/27 23:24:42
  21. 「发现」铁皮石斛仙草之神奇功效用于医用面膜

    原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...

    2024/4/28 5:48:52
  22. 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者

    原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...

    2024/4/30 9:42:22
  23. 广州械字号面膜生产厂家OEM/ODM4项须知!

    原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...

    2024/4/30 9:43:22
  24. 械字号医用眼膜缓解用眼过度到底有无作用?

    原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...

    2024/4/30 9:42:49
  25. 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...

    解析如下&#xff1a;1、长按电脑电源键直至关机&#xff0c;然后再按一次电源健重启电脑&#xff0c;按F8健进入安全模式2、安全模式下进入Windows系统桌面后&#xff0c;按住“winR”打开运行窗口&#xff0c;输入“services.msc”打开服务设置3、在服务界面&#xff0c;选中…...

    2022/11/19 21:17:18
  26. 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。

    %读入6幅图像&#xff08;每一幅图像的大小是564*564&#xff09; f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...

    2022/11/19 21:17:16
  27. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...

    win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面&#xff0c;在等待界面中我们需要等待操作结束才能关机&#xff0c;虽然这比较麻烦&#xff0c;但是对系统进行配置和升级…...

    2022/11/19 21:17:15
  28. 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...

    有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows&#xff0c;请勿关闭计算机”的提示&#xff0c;要过很久才能进入系统&#xff0c;有的用户甚至几个小时也无法进入&#xff0c;下面就教大家这个问题的解决方法。第一种方法&#xff1a;我们首先在左下角的“开始…...

    2022/11/19 21:17:14
  29. win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...

    置信有很多用户都跟小编一样遇到过这样的问题&#xff0c;电脑时发现开机屏幕显现“正在配置Windows Update&#xff0c;请勿关机”(如下图所示)&#xff0c;而且还需求等大约5分钟才干进入系统。这是怎样回事呢&#xff1f;一切都是正常操作的&#xff0c;为什么开时机呈现“正…...

    2022/11/19 21:17:13
  30. 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...

    Win7系统开机启动时总是出现“配置Windows请勿关机”的提示&#xff0c;没过几秒后电脑自动重启&#xff0c;每次开机都这样无法进入系统&#xff0c;此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一&#xff1a;开机按下F8&#xff0c;在出现的Windows高级启动选…...

    2022/11/19 21:17:12
  31. 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...

    有不少windows10系统用户反映说碰到这样一个情况&#xff0c;就是电脑提示正在准备windows请勿关闭计算机&#xff0c;碰到这样的问题该怎么解决呢&#xff0c;现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法&#xff1a;1、2、依次…...

    2022/11/19 21:17:11
  32. 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...

    今天和大家分享一下win7系统重装了Win7旗舰版系统后&#xff0c;每次关机的时候桌面上都会显示一个“配置Windows Update的界面&#xff0c;提示请勿关闭计算机”&#xff0c;每次停留好几分钟才能正常关机&#xff0c;导致什么情况引起的呢&#xff1f;出现配置Windows Update…...

    2022/11/19 21:17:10
  33. 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...

    只能是等着&#xff0c;别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚&#xff0c;只能是考虑备份数据后重装系统了。解决来方案一&#xff1a;管理员运行cmd&#xff1a;net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...

    2022/11/19 21:17:09
  34. 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?

    原标题&#xff1a;电脑提示“配置Windows Update请勿关闭计算机”怎么办&#xff1f;win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢&#xff1f;一般的方…...

    2022/11/19 21:17:08
  35. 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...

    关机提示 windows7 正在配置windows 请勿关闭计算机 &#xff0c;然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;关机提示 windows7 正在配…...

    2022/11/19 21:17:05
  36. 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...

    钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...

    2022/11/19 21:17:05
  37. 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...

    前几天班里有位学生电脑(windows 7系统)出问题了&#xff0c;具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面&#xff0c;长时间没反应&#xff0c;无法进入系统。这个问题原来帮其他同学也解决过&#xff0c;网上搜了不少资料&#x…...

    2022/11/19 21:17:04
  38. 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...

    本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法&#xff0c;并在最后教给你1种保护系统安全的好方法&#xff0c;一起来看看&#xff01;电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中&#xff0c;添加了1个新功能在“磁…...

    2022/11/19 21:17:03
  39. 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...

    许多用户在长期不使用电脑的时候&#xff0c;开启电脑发现电脑显示&#xff1a;配置windows更新失败&#xff0c;正在还原更改&#xff0c;请勿关闭计算机。。.这要怎么办呢&#xff1f;下面小编就带着大家一起看看吧&#xff01;如果能够正常进入系统&#xff0c;建议您暂时移…...

    2022/11/19 21:17:02
  40. 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...

    配置windows update失败 还原更改 请勿关闭计算机&#xff0c;电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容&#xff0c;让我们赶快一起来看一下吧&#xff01;配置windows update失败 还原更改 请勿关闭计算机&#x…...

    2022/11/19 21:17:01
  41. 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...

    不知道大家有没有遇到过这样的一个问题&#xff0c;就是我们的win7系统在关机的时候&#xff0c;总是喜欢显示“准备配置windows&#xff0c;请勿关机”这样的一个页面&#xff0c;没有什么大碍&#xff0c;但是如果一直等着的话就要两个小时甚至更久都关不了机&#xff0c;非常…...

    2022/11/19 21:17:00
  42. 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...

    当电脑出现正在准备配置windows请勿关闭计算机时&#xff0c;一般是您正对windows进行升级&#xff0c;但是这个要是长时间没有反应&#xff0c;我们不能再傻等下去了。可能是电脑出了别的问题了&#xff0c;来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...

    2022/11/19 21:16:59
  43. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

    我们使用电脑的过程中有时会遇到这种情况&#xff0c;当我们打开电脑之后&#xff0c;发现一直停留在一个界面&#xff1a;“配置Windows Update失败&#xff0c;还原更改请勿关闭计算机”&#xff0c;等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢&#xff0…...

    2022/11/19 21:16:58
  44. 如何在iPhone上关闭“请勿打扰”

    Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...

    2022/11/19 21:16:57