我正在编写一个基本代码来添加两个矩阵,并记下单线程和2个或更多线程所用的时间。在该方法中,首先在THREADS段数中划分给定的两个矩阵(随机初始化),然后将这些段中的每一个发送到加法模块,该模块由pthread_create
调用启动。并行加法函数的参数如下。
struct thread_segment
{
matrix_t *matrix1, *matrix2, *matrix3;
int start_row, offset;
};
指向两个源矩阵和一个目标矩阵的指针。 (一旦源和目的地可能指向相同的矩阵)。 start_row
是特定线程应该开始添加的行,offset
告诉这个线程应该从start_row
开始添加多少。
matrix_t
是一个简单的结构,定义如下:
typedef struct _matrix_t
{
TYPE **mat;
int r, c;
} matrix_t;
我用2个线程编译它,但是当我用10000 x 10000矩阵运行时(几乎)没有加速。我正在使用time -p
程序记录运行时间。
矩阵随机初始化也像上面那样并行完成。
我认为这是因为所有线程都在同一个矩阵地址区域工作,可能是因为瓶颈并没有加速。虽然所有线程都可以在矩阵的不同段上工作,但它们不会重叠。
之前我实现了并行mergesort和quicksort,它也显示了类似的特性,当我将特定线程要处理的数据段复制到新分配的内存时,我能够获得加速。
我的问题是这是因为:
在这种情况下,如果它是一个内存瓶颈,那么每个并行程序是否都使用独占内存区域,即使在没有互斥锁的情况下可以多次访问共享内存上的线程?
修改
当我制作像
这样的矩阵段时,我可以看到加速 curr = 0;
jump = matrix1->r / THREADS;
for (i=0; i<THREADS; i++)
{
th_seg[i].matrix1 = malloc (sizeof (matrix_t));
th_seg[i].matrix1->mat = &(matrix1->mat[curr]);
th_seg[i].matrix1->c = matrix1->c;
th_seg[i].matrix1->r = jump;
curr += jump;
}
即在传递之前,在结构中分配要由此线程处理的矩阵的基地址并存储行数。所以现在每个矩阵的基地址对于每个线程都是不同的。但只有当我添加一些小尺寸矩阵100 x 100说,多次。在每次迭代中调用并行添加之前,我正在重新分配随机值。加速注意到这里是真的吗?还是由于其他一些现象的影响?
答案 0 :(得分:2)
要优化内存使用情况,您可能需要查看loop tiling。这将有助于缓存内存更新。在这种方法中,您可以将矩阵划分为更小的块,以便缓存可以保存更长时间的值,而不需要经常更新它。
另请注意,创建多个线程只会增加在它们之间切换的开销。
为了感觉正确的实现可以影响并发程序的运行时间,这些是在天真,cocnurrent和tiling-concurrent中将两个矩阵相乘的程序的结果:
seconds name
10.72 simpleMul
5.16 mulThread
3.19 tilingMulThread