webassembly003 ggml GGML Tensor Library part-3

news2024/11/19 5:32:19

关于pthread_create()和pthread_join()

#include <stdio.h>
#include <pthread.h>
 
void *thread_func(void *arg) {
  int *num = (int *)arg;
  printf("Hello from thread! arg=%d\n", *num);
  pthread_exit(NULL);
}
 
int main() {
  pthread_t thread;
  int arg = 10;
 
  if (pthread_create(&thread, NULL, thread_func, &arg) != 0) {
    printf("Failed to create thread\n");
    return 1;
  }
 
  if (pthread_join(thread, NULL) != 0) {
    printf("Failed to join thread\n");
    return 1;
  }
 
  printf("Main thread ends\n");
  return 0;
}

         是否是在pthread_join后线程才会执行?
         不是。在线程创建后,可以立即执行线程函数。但是如果在主线程中调用了pthread_join函数,主线程会等待被等待的线程执行完毕后再继续执行。所以在pthread_join函数之后,被等待的线程才会执行完毕。
在这里插入图片描述
         但是初始化的参数(比如以下片段中的node)是错误的,如何使得不计算出错呢?

            workers[j] = (struct ggml_compute_state) {
                    .thrd   = 0,
                    .params = {
                            .type  = GGML_TASK_COMPUTE,
                            .ith   = j + 1,
                            .nth   = n_threads,
                            .wsize = cgraph->work ? ggml_nbytes(cgraph->work) : 0,
                            .wdata = cgraph->work ? cgraph->work->data : NULL,
                    },
                    .node   = NULL,
                    .shared = &state_shared,
            };
            int rc = pthread_create(&workers[j].thrd, NULL, ggml_graph_compute_thread, &workers[j]);

        自旋锁;自旋锁的指的是线程在获取锁时,如果发现锁已经被其他线程占用,会进入一个忙等待的状态,不断地检查锁是否被释放。这个过程称为旋转,因为线程会像旋转一样不断地尝试获取锁,直到成功为止。旋转是一种快速的等待方式,可以减少线程切换的开销,但也会消耗CPU资源。
        项目使用自旋锁当参数被正确设置之后才会执行

thread_ret_t ggml_graph_compute_thread(void * data) {
	//将data指针转换为ggml_compute_state类型的指针state。
    struct ggml_compute_state * state = (struct ggml_compute_state *) data;

    const int n_threads = state->shared->n_threads;

    while (true) {
        // 如果当前线程是最后一个准备好的线程
        if (atomic_fetch_add(&state->shared->n_ready, 1) == n_threads - 1) {
            atomic_store(&state->shared->has_work, false);//则将 has_work 设置为 false
        } else {
            // 如果 has_work 为 true,则等待直到 has_work 变为 false
            while (atomic_load(&state->shared->has_work)) {
                // 如果 stop 为 true,则返回 0
                if (atomic_load(&state->shared->stop)) {
                    return 0;
                }
                ggml_lock_lock  (&state->shared->spin);
                ggml_lock_unlock(&state->shared->spin);
            }
        }

        atomic_fetch_sub(&state->shared->n_ready, 1);

        // 等待有工作要做
        while (!atomic_load(&state->shared->has_work)) {
            // 如果 stop 为 true,则返回 0
            if (atomic_load(&state->shared->stop)) {
                return 0;
            }
            ggml_lock_lock  (&state->shared->spin);
            ggml_lock_unlock(&state->shared->spin);
        }

        // 检查是否应该停止
        if (atomic_load(&state->shared->stop)) {
            break;
        }

        // 执行计算并将 state->node 设置为 NULL
        if (state->node) {
            ggml_compute_forward(&state->params, state->node);
            state->node = NULL;
        } else {
            break;
        }
    }

    return 0;
}

     在非阶段 GGML_TASK_INIT , GGML_TASK_FINALIZE执行运算

void ggml_compute_forward_add_f32(
        const struct ggml_compute_params * params,
        const struct ggml_tensor * src0,
        const struct ggml_tensor * src1,
        struct ggml_tensor * dst) {
    GGML_ASSERT(ggml_are_same_shape(src0, src1) && ggml_are_same_shape(src0, dst));

    if (params->type == GGML_TASK_INIT || params->type == GGML_TASK_FINALIZE) {
        return;
    }

    const int ith = params->ith;
    const int nth = params->nth;

    const int n  = ggml_nrows(src0);
    const int nc = src0->ne[0];

    const size_t nb00 = src0->nb[0];
    const size_t nb01 = src0->nb[1];

    const size_t nb10 = src1->nb[0];
    const size_t nb11 = src1->nb[1];

    const size_t nb0 = dst->nb[0];
    const size_t nb1 = dst->nb[1];

    GGML_ASSERT( nb0 == sizeof(float));
    GGML_ASSERT(nb00 == sizeof(float));

    if (nb10 == sizeof(float)) {
        const int j0 = (n/nth)*ith;
        const int j1 = ith == nth - 1 ? n : (n/nth)*(ith + 1);

        for (int j = j0; j < j1; j++) {
            ggml_vec_add_f32(nc,
                             (float *) ((char *) dst->data  + j*nb1),
                             (float *) ((char *) src0->data + j*nb01),
                             (float *) ((char *) src1->data + j*nb11));
        }
    } else {
        // src1 is not contiguous
        for (int j = ith; j < n; j += nth) {
            float * dst_ptr  = (float *) ((char *) dst->data  + j*nb1);
            float * src0_ptr = (float *) ((char *) src0->data + j*nb01);
            for (int i = 0; i < nc; i++) {
                float * src1_ptr = (float *) ((char *) src1->data + j*nb11 + i*nb10);

                dst_ptr[i] = src0_ptr[i] + *src1_ptr;
            }
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

解锁开发中的创意:用户为中心的设计思维的力量

引言 设计思维&#xff0c;起源于20世纪60年代&#xff0c;是一种解决问题的方法。它不仅仅是设计师的专利&#xff0c;而是一种可以广泛应用于各种行业和领域的方法。设计思维强调了用户至中的重要性&#xff0c;认为任何问题的解决都应该从用户的需求出发。这种方法鼓励我们…

反转链表+交换两个链表的节点

目录 ​编辑 一&#xff0c;反转链表 1.题目描述 2.例子 3.题目接口 4.分析以及解题代码 1.迭代法 2.递归写法 二&#xff0c;两两交换两个链表中的节点 1.题目描述 2.例子 3.题目接口 4.题目分析以及解法 一&#xff0c;反转链表 1.题目描述 首先来看看反转链表的…

主流深度学习框架及神经网络模型汇总

目录 主流深度学习框架及神经网络模型汇总 一、人工智能的研究领域和分支 二、主流深度学习框架​编辑 1.TensorFlow 2.PyTorch 3.PaddlePaddle 4.Keras 5.Caffe/Caffe2 6.MXNet 7.Theano 8.Torch 9.CNTK 10.ONNX 三、深度学习移动端推理框架 1.TensorRT 2.TF-…

LabVIEW是如何控制硬件的?

概述 工程 师 和 科学 家 可以 使用 LabVIEW 与 数千 种 不同 的 硬件 设备 无缝 集成&#xff0c; 并 通过 方便 的 功能 和 跨 所有 硬件 的 一致 编 程 框架 帮助 节省 开发 时间。 内容 通过更简单的系统集成节省开发时间 连接到任何硬件 NI 硬件 第三方硬件 快速找到…

数据库事务四大特性

事务的4大特性&#xff08;ACID&#xff09;&#xff1a; 原子性(Atomicity)&#xff1a; 事务是数据库的逻辑工作单位&#xff0c;它对数据库的修改要么全部执行&#xff0c;要么全部不执行。 一致性(Consistemcy)&#xff1a; 事务前后&#xff0c;数据库的状态都满足所有的完…

Python之defaultdict方法详解

文章目录 字典dict介绍collections.defaultdict类 字典dict介绍 python中的dict是一个重要的数据类型,用“键”(key)来索引&#xff0c;表示为dict(key: val, …),有以下特征&#xff1a; 键可以是任何不可变(immutable)数据类型不可变数据类型有&#xff1a;数字&#xff0c…

嵌入式软件设计

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和…

手写数字识别之损失函数

目录 交叉熵 手写数字识别之损失函数 分类任务的损失函数 Softmax函数 交叉熵的简单理解&#xff1a;真实分布与非真实分布的交叉&#xff0c;完全对应&#xff0c;熵为0 交叉熵的代码实现 交叉熵 给定一个策略, 交叉熵就是在该策略下猜中颜色所需要的问题的期望值。更普…

三、JVM监控及诊断工具-GUI篇

目录 一、工具概述二、jconsole&#xff08;了解即可&#xff09;1、基本概述2、启动3、三种连接方式4、作用 三、Visual VM 一、工具概述 二、jconsole&#xff08;了解即可&#xff09; 1、基本概述 从Java5开始&#xff0c;在JDK中自带的Java监控和管理控制台用于对JVM中内…

【mindspore学习】环境配置

本次实验搭配的环境是 CUDA 11.6 CUDNN v8.9.4 TensorRT-8.4.1.5 mindspore 2.1.0。 1、配置 Nvidia 显卡驱动 如果原来的主机已经安装了 nvidia 驱动&#xff0c;为避免版本的冲突&#xff0c;建议先清除掉旧的 nvidia驱动 sudo apt-get --purge remove nvidia* sudo apt…

土豆叶病害识别(图像连续识别和视频识别)

效果视频&#xff1a;土豆叶病害识别&#xff08;Python代码&#xff0c;pyTorch框架&#xff0c;视频识别&#xff09;_哔哩哔哩_bilibili 代码运行要求&#xff1a;Torch库>1.13.1&#xff0c;其它库无版本要求 1..土豆叶数据集主要包好三种类别&#xff08;Early_Blight…

分布式训练 最小化部署docker swarm + docker-compose落地方案

目录 背景&#xff1a; 前提条件&#xff1a; 一、docker环境初始化配置 1. 安装nvidia-docker2 2. 安装docker-compose工具 3. 获取GPU UUID 4. 修改docker runtime为nvidia&#xff0c;指定机器的UUID 二、docker-swarm 环境安装 1. 初始化swarm管理节点 2. 加入工…

Redis数据类型全总结【万字总结】

文章目录 前言一、String1、内部实现2、应用场景缓存对象常规计数分布式锁共享 Session 信息 3、常用指令 二、List1、内部实现2、应用场景消息队列List 作为消息队列有什么缺陷 3、常用指令 三、Hash1、内部实现2、应用场景缓存对象购物车 3、常用指令 四、Set1、内部实现2、应…

10万字智慧政务大数据平台项目建设方案222页[Word]

导读&#xff1a;原文《10万字智慧政务大数据平台项目建设方案222页[Word]》&#xff08;获取来源见文尾&#xff09;&#xff0c;本文精选其中精华及架构部分&#xff0c;逻辑清晰、内容完整&#xff0c;为快速形成售前方案提供参考。 1.1 项目建设目标 推进市一级政府搭建数…

测试.net开源音频库NAudio

微信公众号“dotNET跨平台”看到一篇文章《【.NET】使用NAudio实现录音功能》介绍基于NAudio实现录音功能&#xff08;参考文献1&#xff09;。NAudio是开源.net音频库&#xff0c;其支持播放多种格式的音频&#xff08;WAV、AIFF、MP3、WMA等&#xff09;、音频格式转换、录音…

lnmp架构-mysql

1.MySQL数据库编译 make完之后是这样的 mysql 初始化 所有这种默认不在系统环境中的路径里 就这样加 这样就可以直接调用 不用输入路径调用 2.初始化 重置密码 3.mysql主从复制 配置master 配置slave 当master 端中还没有插入数据时 在server2 上配slave 此时master 还没进…

【MongoDB系列】-MongoDB详解(一文让你明白什么是MongoDB)

MongoDB简介 MongoDB 是一个开源的、跨平台的、面向文档的、基于分布式文件存储的数据库系统&#xff0c;MongoDB 是由 C 语言开发&#xff0c;旨在为 Web 应用提供可扩展的高性能数据存储解决方案。在高负载的情况下&#xff0c;通过添加更多的节点&#xff0c;可以保证服务器…

基于YOLOV8模型的人脸口罩目标检测系统(PyTorch+Pyside6+YOLOv8模型)

摘要&#xff1a;基于YOLOV8模型的人脸口罩目标检测系统可用于日常生活中检测与定位人脸口罩&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的目标检测&#xff0c;另外本系统还支持图片、视频等格式的结果可视化与结果导出。本系统采用YOLOv8目标检测算法训练数…

基于android的学生公寓后勤系统/学生公寓管理系统APP

摘 要 随着网络科技的发展&#xff0c;移动智能终端逐渐走进人们的视线&#xff0c;相关应用越来越广泛&#xff0c;并在人们的日常生活中扮演着越来越重要的角色。因此&#xff0c;关键应用程序的开发成为影响移动智能终端普及的重要因素&#xff0c;设计并开发实用、方便的应…

Git企业开发控制理论和实操-从入门到深入(四)|Git的远程操作|Gitee

前言 那么这里博主先安利一些干货满满的专栏了&#xff01; 首先是博主的高质量博客的汇总&#xff0c;这个专栏里面的博客&#xff0c;都是博主最最用心写的一部分&#xff0c;干货满满&#xff0c;希望对大家有帮助。 高质量博客汇总 然后就是博主最近最花时间的一个专栏…