用多线程并发的方式来计算两个矩阵的乘法_、试用线程的方法编写两个10*10矩阵的相乘的计算程序,用10个线程完成结果矩-程序员宅基地

技术标签: 程序  

要求很简单,计算两个矩阵的乘法。为了加速,这里面使用了pthread库,来并发计算。

基本思路如下图。

比如用两个线程来计算。矩阵A * B。那么就把A分成两份。比如下图,就是0,2,4和1,3,5这两份。

在线程1中计算第0,2,4行和B个列的乘积,在线程2中计算1,3,5行和B各个列的乘积。


思路很简单。最后代码如下:

// pthread.cpp : Defines the entry point for the console application.
//


#include <stdlib.h>
#include "pthread.h"
#include <x86intrin.h>
#include <xmmintrin.h>


int THREADS_COUNT = 4;
pthread_t threads[16];


int PRINT = 0;




void test(int dim);
int * multiplyPthread(int * a, int* b, int dim);
int * multiplySimple(int * a, int* b, int dim);
int mul(int* a, int* b, int row, int col, int dim);


struct THREAD_PARAM {
        int * a;
        int * b;
        int * buffer;
        int dim;
        int index;
        int step;
};


struct THREAD_PARAM params[16];


void output(int * buf, int dim) {
        for (int i=0; i<dim; i++) {
                for (int j=0; j<dim; j++) {
                        printf("%d ", buf[i * dim + j]);
                }
                printf("\n");
        }
        printf("============\n");
}


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


        int size[] = {4, 16, 32, 48, 64, 128, 256, 512, 1024, 2048, 4096};
        for (int i=0; i<8; i++) {
                test(size[i]);
        }
        return 0;
}


void test(int dim) {
        int * a = (int*)malloc(dim * dim * sizeof(int));
        for (int i=0; i<dim; i++) {
                for (int j=0; j<dim; j++) {
                        a[i * dim + j] = i * j + 1;
                }
        }
        int * b = (int*)malloc(dim * dim * sizeof(int));
        for (int i=0; i<dim; i++) {
                for (int j=0; j<dim; j++) {
                        b[i * dim + j] = i * j + 2;
                }
        }


        struct  timeval start0,start1,start2;
        struct  timeval end0,end1,end2;
        unsigned  long diff0, diff1,diff2;
        gettimeofday(&start0,NULL);


        int * result = multiplySimple(a, b, dim);
        gettimeofday(&end0,NULL);




        gettimeofday(&start1,NULL);
        int * resultPthread = multiplyPthread(a, b, dim);
        gettimeofday(&end1,NULL);


      //  gettimeofday(&start2,NULL);
      //  int * resultPthreadSSE = multiplyPthread(a, b, dim, 1);
      //  gettimeofday(&end2,NULL);




        if (PRINT) {
                output(a, dim);
                output(b, dim);
                output(result, dim);
                output(resultPthread, dim);
        //      output(resultPthreadSSE, dim);
        }




        diff0 = 1000000 * (end0.tv_sec-start0.tv_sec)+ end0.tv_usec-start0.tv_usec;
        diff1 = 1000000 * (end1.tv_sec-start1.tv_sec)+ end1.tv_usec-start1.tv_usec;
        //diff2 = 1000000 * (end2.tv_sec-start2.tv_sec)+ end2.tv_usec-start2.tv_usec;        


        printf("(%d) the difference for simple is %ld\n", dim, diff0);
        printf("(%d) the difference for threaded is %ld\n", dim, diff1);
        //printf("(%d) the difference for threaded with SSE is %ld\n", dim, diff2);


        free(result);
        free(resultPthread);
        free(a);
        free(b);
}


int * multiplySimple(int* a, int* b, int dim) {
        int * result = (int*)malloc(dim * dim * sizeof(int));
        int sum = 0;


        for (int i=0; i<dim; i++) {
                for (int j=0; j<dim; j++) {
                        sum = 0;
                        for (int k=0; k<dim; k++) {
                                sum += (a[dim * i +k] * b[dim * k + j]);
                        }
                        result[dim * i + j] = sum;
                }
        }
        return result;
}






void *Calculate(void *param) 
{


   
   struct THREAD_PARAM *p = (struct THREAD_PARAM*)param;


   int dim = p->dim;
   int index = p->index;
   int *a = p->a;
   int *b = p->b;
   int *result = p->buffer;
   int step = p->step;


   int sum = 0;


   for (int i=index; i<dim; i+=step) {
                for (int j=0; j<dim; j+=1) {
                        sum = 0;
                        //  int sum = mul(a, b, i, j, dim);
                        for (int k=0; k<dim; k++) {
                                // printf("cal %d, %d, %d\n", i, j, k);
                                sum += (a[dim * i +k] * b[dim * k + j]);
                        }
                        result[dim * i + j] = sum;
                }
   }
   pthread_exit(NULL);
   return 0;
}


int * multiplyPthread(int* a, int* b, int dim) {


        int * result = (int*)malloc(dim * dim * sizeof(int));


        for (int i=0; i<THREADS_COUNT; i++) {
                params[i].buffer = result;
                params[i].index = i;
                params[i].dim = dim;
                params[i].step = THREADS_COUNT;
                params[i].a = a;
                params[i].b = b;
                int rc = pthread_create(&threads[i], NULL, Calculate, (void *)(&params[i])); 
        }


    for(int t=0; t<THREADS_COUNT; t++) {
        void* status;
        int rc = pthread_join(threads[t], &status);
        if (rc)  {
            printf("ERROR; return code from pthread_join()   is %d\n", rc);
         }
         // printf("Completed join with thread %d status= %ld\n",t, (long)status);
    }
        return result;
}
编译参数:

# clang -O1 -lpthread -Wall mul.c

运行环境:

CentOS7, 4核的CPU,所以这里开了4个线程。

运行结果分析。

当矩阵的大小比较小的时候,普通的矩阵乘法比多线程的算法快得多。这也是可以理解的,因为创建线程需要一定的时间。

当矩阵的大小为64时,多线程的时间和普通单线程的时间基本上相同。

当矩阵的大小大于64时,多线程的时间明显好于单线程。

当矩阵的大小大于256时,多线程的性能达到单线程的4倍左右,很理想:

(4) the difference for simple is 1
(4) the difference for threaded is 420
(16) the difference for simple is 10
(16) the difference for threaded is 117
(32) the difference for simple is 63
(32) the difference for threaded is 151
(48) the difference for simple is 177
(48) the difference for threaded is 196

(64) the difference for simple is 379
(64) the difference for threaded is 329

(128) the difference for simple is 4456
(128) the difference for threaded is 2376
(256) the difference for simple is 40366
(256) the difference for threaded is 10581
(512) the difference for simple is 387046
(512) the difference for threaded is 97153


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/lff0305/article/details/50171641

智能推荐

MyEclipse2015创建配置Web+Maven项目-程序员宅基地

文章浏览阅读174次。MyEclipse2015创建配置Web+Maven项目 首先我的MyEclipse版本是2015 stable 2.0,在MyEclipse中创建Maven项目通常有两种常见的方式,它们分别是:New Maven ProjectNew Web Project &amp; Add maven support..._创建web项目要configure maven project support settings

电脑华为magicbook电脑更新系统后指纹用不了的解决办法_荣耀笔记本指纹驱动-程序员宅基地

文章浏览阅读5.3k次。华为matebook电脑更新系统后指纹使用不了解决方法_荣耀笔记本指纹驱动

CentOS OpenStack Pike tacker 之 mistral 安装实录_python安装mistral large包-程序员宅基地

文章浏览阅读582次。格式有点乱有空再整理一、安装mistral组件(官网手册为Ubuntu版,操作有点坑)“For information on how to install and configure the Workflow service for Red Hat Enterprise Linux 7 and CentOS 7, refer to theInstallation guide for Ub..._python安装mistral large包

不平衡数据下的机器学习方法简介_数据不对等的样本使用机器学习,选用哪种方式-程序员宅基地

文章浏览阅读2.8k次,点赞3次,收藏6次。本文转自:http://baogege.info/2015/11/16/learning-from-imbalanced-data/引言不管是在学术界还是工业界,不平衡学习已经吸引了越来越多的关注,不平衡数据的场景也出现在互联网应用的方方面面,如搜索引擎的点击预测(点击的网页往往占据很小的比例),电子商务领域的商品推荐(推荐的商品被购买的比例很低),信用卡欺诈检测,网络攻击识别等等_数据不对等的样本使用机器学习,选用哪种方式

mPaas-RPC拦截器各种场景下的使用指南_mpass 拦截请求-程序员宅基地

文章浏览阅读371次。mPaas-RPC拦截器各种场景下的使用指南一背景二 RPC调用原理三 拦截器四 preHandle场景五 postHandle场景六 exceptionHandle场景七 H5场景一背景金融级移动开发平台 mPaaS(Mobile PaaS)为 App 开发、测试、运营及运维提供云到端的一站式解决方案,能有效降低技术门槛、减少研发成本、提升开发效率,协助企业快速搭建稳定高质量的移动应用。其中移动网关服务(Mobile Gateway Service,简称 MGS)作为mPaas最重要的组件之一,连接了_mpass 拦截请求

java中List集合遍历和迭代器遍历_java迭代器和list区别-程序员宅基地

文章浏览阅读1.6w次。java中List集合遍历和迭代器遍历_java迭代器和list区别

随便推点

vscode windows版本安装SFTP配置sftp_vsdoce sftp证书-程序员宅基地

文章浏览阅读805次。龚帅立出品## 1.在vscode中下载sftp插件在vscode中快捷键 ctrl+shift+P 打开指令窗口,输入extension:install,回车,左侧即打开扩展安装的界面上面这一步相当于点击左侧的拓展ctrl+shift+x在搜索框中输入SFTP,第一个就是需要安装的,点安装 。## 2.在vscode的工程中配置sftp.json然后快捷键 ctrl+shift+P 打开指令窗口,输入sftp:config,回车,就会在当前工作工程的.vscode文件夹下生成一个sft_vsdoce sftp证书

阿里云lanp配置-程序员宅基地

文章浏览阅读68次。在镜像市场中选择这个,服务器要有独立公网IP装好了之后,在服务器安全组里添加允许访问80以及8080端口现在访问IP应该是没有任何响应的,因为nginx还未开启根据镜像的说明书(官方链接)一些基本的操作命令Apache 配置文件路径:/etc/httpd/Apache网站主目录:/var/www/htmlApache主配置文件:/etc/httpd/conf/...

MyCat之超详细安装教程_wget mycat-程序员宅基地

文章浏览阅读382次。安装jdk81.使用wget方式下载并安装2.检查是否安装wget安装命令如下:[root@a6e474908097 tools]# yum -y install wget3.下载jdk1.8[root@a6e474908097 tools]# wget http://dl.mycat.org.cn/jdk-8u20-linux-x64.tar.gz4.解压文件[root@a6..._wget mycat

perl python和linux的关系_Python与Perl不能说的秘密-程序员宅基地

文章浏览阅读230次。最近想学一下Python,同时也想了解了下perl,就到处找了找相关的资料,以下内容都是我在网上找的,版权归原作者所有。一、简介1、 PythonPython的创始人为Guido van Rossum。1989年圣诞节期间,在阿姆斯特丹,Guido为了打发圣诞节的无趣,决心开发一个新的脚本解释程序,做为 ABC 语言的一种继承。之所以选中 Python(大蟒蛇的意思)作为程序的名字,是因为他是一..._为什么perl与linux密不可分

CPU_Z计算机主板性能表,只为高端玩家 七款Z97高规主板推荐-程序员宅基地

文章浏览阅读5.9k次。1高端以及性价比 Z97主板推荐作为现在电脑的标配,USB3.0已经全面普及了,接下来就是更新更强的USB3.1时代,USB3.1数据传输速度提升可至速度10Gbps,读写速度可达700MB/秒,而且它完全向下兼容现有的USB连接器与线缆。各大主板厂商也正密锣紧鼓地筹备USB3.1主板,但目前仅有华硕率先发布解决方案,首批USB3.1主板即将上市。USB3.1主板目前只集中在Intel..._电脑主板型号及性能表

PB实现微信、支付宝、新大陆星POS扫码支付接口_pb 微信扫码付接口文档-程序员宅基地

文章浏览阅读1.7k次。PB调用C#动态库实现新大陆星POS扫码支付接口。_pb 微信扫码付接口文档

推荐文章

热门文章

相关标签