使用win32线程的矩阵乘法

Posted

技术标签:

【中文标题】使用win32线程的矩阵乘法【英文标题】:Matrix Multiplication Using win32 threads 【发布时间】:2011-05-20 01:28:35 【问题描述】:

我不知道我的代码出了什么问题……它总是在所有元素中返回零。提示问题出在哪里会很好:)

#include <iostream>
#include <stdio.h>
#include <cstdlib>
#include <ctime>
#include <windows.h>

using namespace std;

int nGlobalCount = 0;
int thread_index = 0;
int num_of_thr=5;

int a[4][4], b[4][4], c[4][4];
int i, j, k;

struct v 
    int i; /*row*/
    int j; /*column*/
;

DWORD ThreadProc (LPVOID lpdwThreadParam ) 
    //
    struct v *input = (struct v *)lpdwThreadParam;
    int avg=4*4/num_of_thr;
    int count=0;

    for(int i = 0; i <= 3 ; i++) 
        for(int j = 0; j <= 3; j++) 
            int sum=0;
            for ( k = 0 ; k <= 3; k++) 
               sum=sum+((a[input->i][k])*(b[k][input->j]));
                c[input->i][input->j]=sum;
                count++;
            
        
    

    //Print Thread Number
    //printf ("Thread #: %d\n", *((int*)lpdwThreadParam));
    //Reduce the count
    return 0;


int main() 
    //    int x=0;
    cout<<"enter no of threads : ";
    cin>>num_of_thr;
    DWORD ThreadIds[num_of_thr];
    HANDLE ThreadHandles[num_of_thr];
    //struct v 
    //    int i; /*row*/
    //    int j; /*column*/
    //;

    struct v data[num_of_thr];
    int i , j , k;

    for ( int i = 0 ; i <= 3; i++) 
        for (int j = 0 ; j <= 3 ; j++) 
            a[i][j] = rand() % 10;
            b[i][j] = rand() % 10;
            c[i][j] = 0;
        
    

    for(int i = 0; i < num_of_thr/2; i++) 
        for(int j = 0; j < num_of_thr/2; j++) 
            data[thread_index].i = i;
            data[thread_index].j = j;

            ThreadHandles[thread_index] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&ThreadProc, &data[thread_index], 0,&ThreadIds[thread_index]);

            thread_index++;
        
    

    WaitForMultipleObjects(num_of_thr, ThreadHandles, TRUE, INFINITE);
    cout<<"The resultant matrix is "<<endl;
    for ( i = 0 ; i < 4; i++) 
        for ( j = 0 ; j < 4 ; j++)
            cout<<c[i][j]<<" ";
        cout<<endl;
    
    for (int i=0; i<num_of_thr; i++)
        CloseHandle(ThreadHandles[i]);
    return 0;

【问题讨论】:

【参考方案1】:

一目了然,循环中的 sum 声明看起来很粗略。

for(int i = 0; i <= 3 ; i++) 
    for(int j = 0; j <= 3; j++) 
        for ( k = 0 ; k <= 3; k++)

            
            int sum=sum+((a[input->i][k])*(b[k][input->j])); // this declaration seems wrong
            c[input->i][input->j]=sum;
            count++;
            
        
    

您重新声明 sum 的每个内部循环,实际上将其设为 0。您可能希望将声明从分配中向上移动一到两个循环,具体取决于您要实现的目标。

【讨论】:

【参考方案2】:

您是否意识到您有两组独立的变量,分别命名为 a、b 和 c?一个是函数 main 的局部变量,另一个是整个程序的静态变量。我怀疑这不是你想要的。尝试删除 main 本地的那个。

马丁

【讨论】:

@Loka :您是否在编辑后尝试过运行代码?这可能是您问题的根源。【参考方案3】:

除了前面提到的其他问题之外,我在探索时发现了一些事情:

你用什么编译这个?使用 VC++ 2010 它“工作”,因为它输出非零,尽管它抱怨 DWORD ThreadIds[num_of_thr]; 数组声明具有非常量数组大小(我刚刚将 num_of_thr 设为常量并将 cin 注释掉快速测试)。 您确定输入的线程数是有效的cin &gt;&gt; num_of_thr; 例如,如果num_of_thr 为0,这将解释零输出。在这里为num_of_thr 提供一个简单的cout 会很有用。 在以for(int i = 0; i &lt; num_of_thr/2; i++) 开头的数据初始化循环中,您没有正确计算线程数,这将导致数组下溢或溢出。例如,如果 num_of_thr 为 5,则 num_of_thr/2 为 2,这将导致仅初始化元素 0..3,而最后一个元素未初始化。数组下溢在技术上是可以的,尽管稍后的CloseHandle() 调用在尝试释放基本上随机的句柄时会失败。如果您输入大量线程,您将溢出所有数组(例如,尝试使用num_of_thr=10)。 如果仍然无法正常工作,请尝试删除线程以查看线程或代码本身是否是问题的根源。例如,您可以在循环中手动调用ThreadProc() 函数,而不是从线程中调用。使用调试器跟踪程序或将日志输出到标准输出/文件(这也适用于线程模型)。 首先我会使用一些固定值而不是随机源矩阵,但结果已知。这将更容易确定代码是否实际计算了正确的结果。

【讨论】:

感谢它适用于 9 个线程(即每个线程对一个元素进行操作),但对于更少的线程仍然无效。我想我应该像你说的那样重做初始化循环:) .. 谢谢

以上是关于使用win32线程的矩阵乘法的主要内容,如果未能解决你的问题,请参考以下文章

大矩阵的Opencv乘法

Java中的多线程矩阵乘法

使用 CUDA 进行矩阵乘法:2D 块与 1D 块

numpy/pandas矩阵乘法的多线程?

C++中的多线程矩阵乘法

在矩阵乘法中使用 C++2011 线程而不是 OpenMP 时出现异常加速