IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> fork join和for循环结合的实际应用 -> 正文阅读

[Java知识库]fork join和for循环结合的实际应用

fork join 结构中,父进程会被阻塞直到所有的子进程结束;
fork...join_any 结构中,父进程会被阻塞直到其中任意一个子进程结束;
fork.... join_none 父进程会立即与产生的所有进程并发执行。
fork中每条语句并行执行 ,如果将多个语句封装在一个 begin end 块中会将整个块 作为单个进程执行,其中每条语句顺序地执行。
实际应用:
实际应用中,我们通常会使用了for循环和fork join_none来并行启动多个进程(这样不用写哪些重复的代码)。
for+fork...join
首先说明使用for+fork...join是 不能实现并行启动多个进程,因为fork...join是会阻塞父进程的,外部的for循环是主程序一部分,所以fork...join也会阻塞for循环的进行。如下代码的结果·中,从打印的时间,看三次for循环并没有并行(即使使用automatic也一样的,这是fork...join阻塞父进程决定的):
`timescale 1ns/1ns

module top();
	int a;
	int i;

	task lab(int i);
		a<=i;
		#1;
		$display("a=%0d,time=%0t",i,$time);
	endtask
	initial begin

		for(int j=0;j<3;j++) begin
			fork
				$display("j=%0d,time=%0t",j,$time);
				lab(j);
			join
		end
		$display("main,time=%0t",$time);
		#10;
		$finish;
	end
endmodule

结果:

*Verdi* : Begin traversing the scopes, layer (0).
*Verdi* : Enable +all dumping.
*Verdi* : End of traversing.
ucli% run 1000ns
j=0,time=0
a=0,time=1
j=1,time=1
a=1,time=2
j=2,time=2
a=2,time=3
main,time=3
$finish called from file "lab13_fork.sv", line 22.
$finish at simulation time                   13
           V C S   S i m u l a t i o n   R e p o r t 

for+fork...join_none

fork...join_none则不会阻塞父进程,因此使用for+fork...join_none才能实现并行启动多个进程。当我们将上面代码改为fork...join_none:

代码:

`timescale 1ns/1ns

module top();
	int a;
	int i;

	task lab(int i);
		a<=i;
		#1;
		$display("a=%0d,time=%0t",i,$time);
	endtask
	initial begin

		for(int j=0;j<3;j++) begin
			fork
				$display("j=%0d,time=%0t",j,$time);
				lab(j);
			join_none
		end
		$display("main,time=%0t",$time);
		#10;
		$finish;
	end
endmodule

结果:

*Verdi* : Begin traversing the scopes, layer (0).
*Verdi* : Enable +all dumping.
*Verdi* : End of traversing.
ucli% run 1000ns
main,time=0
j=3,time=0
j=3,time=0
j=3,time=0
a=3,time=1
a=3,time=1
a=3,time=1
$finish called from file "lab13_fork.sv", line 22.
$finish at simulation time                   10
           V C S   S i m u l a t i o n   R e p o r t 

可以看到打印的三个时间是一样的了说明是并行,但是a的值是一样的,这是因为SV中function和task默认都是静态的,这些静态的function和task里面的局部变量会使用共享的静态存储区,所以不同的线程之间会窜用这些变量,可以在unction和task加入automatic改做动态的,此外还需要一个动态变量来接收for循环的j,不然结果依然,这是因为并行启动时j已经等于3了,此时各个进程会共用一个j。改变后代码如下:

`timescale 1ns/1ns

module top();
	int a;
	int i;

	task automatic lab(int i);
		a<=i;
		#1;
		$display("a=%0d,time=%0t",i,$time);
	endtask
	initial begin

		for(int j=0;j<3;j++) begin
			fork
				automatic int k=j;
				$display("k=%0d,time=%0t",k,$time);
				lab(k);
			join_none
		end
		$display("main,time=%0t",$time);
		#10;
		$finish;
	end
endmodule

结果:

*Verdi* : Begin traversing the scopes, layer (0).
*Verdi* : Enable +all dumping.
*Verdi* : End of traversing.
ucli% run 1000ns
main,time=0
k=0,time=0
k=1,time=0
k=2,time=0
a=0,time=1
a=1,time=1
a=2,time=1
$finish called from file "lab13_fork.sv", line 23.
$finish at simulation time                   10
           V C S   S i m u l a t i o n   R e p o r t 

但是上面结果有另外一个问题,如果for循环后面display这个语句执行是和整个循环并行的(打印的time是0),因为fork...join_none并没有阻塞父进程。如果for后面代码依赖for循环内的并行进程时,我们就希望在for内所有进程都执行完再执行for后面的父进程。此时,我们就需要加上一个隔离进程。

for+fork...join_none+fork..join

因为fork...join可以阻塞父进程,所以我们可以在for外面在套一个fork...join作为隔离,此外我们需要使用wait fork来等待子进程执行完成。如下结果中我们可以看到display的打印已经在time=1。说明for后面主进程是在并行进程执行完之后执行的。

代码:

`timescale 1ns/1ns

module top();
	int a;
	int i;

	task automatic lab(int i);
		a<=i;
		#1;
		$display("a=%0d,time=%0t",i,$time);
	endtask
	initial begin
		fork 
			begin
				for(int j=0;j<3;j++) begin
					fork
						automatic int k=j;
						$display("k=%0d,time=%0t",k,$time);
						lab(k);
					join_none
				end
				wait fork;
			end
		join
		$display("main,time=%0t",$time);
		#10;
		$finish;
	end
endmodule

结果:

*Verdi* : Enable +all dumping.
*Verdi* : End of traversing.
ucli% run 1000ns
k=0,time=0
k=1,time=0
k=2,time=0
a=0,time=1
a=1,time=1
a=2,time=1
main,time=1
$finish called from file "lab13_fork.sv", line 27.
$finish at simulation time                   11
           V C S   S i m u l a t i o n   R e p o r t 

在实际代码中,我们可能需要同时送不同的item给不同的sequencer,而这不同的item之间又需要同步发送,那么就需要使用这样的组合。比如下面代码:

		fork
			begin
			for(int j=0;j<seq_id.size();j++) begin
				fork 
					automatic int k=j;
					begin
						string tr_name=$sformatf("px_tr_seq%0d",k);
						px_tr_img[k]=pixel_transaction::type_id::create(tr_name, ,get_full_name());
						`uvm_info("image_gen_sequence",$sformatf("Send sequence%0d's px_tr_img ...",seq_id[k]),UVM_LOW);
						start_item(px_tr_img[k],-1,p_sequencer.px_sqr[k]);
						px_tr_img[k].copy(px_tr);
						for(int i=0;i<(2+1);i++) begin//parameter from ghl
							px_tr_img[k].data_in0[i]=block_img[k][0][i];
							px_tr_img[k].data_in1[i]=block_img[k][1][i];
						end
						finish_item(px_tr_img[k]);
						`uvm_info("image_gen_sequence",$sformatf("Finish send sequence%0d's px_tr_img ...",seq_id[k]),UVM_LOW);
					end
				join_none
			end

			wait fork;
			end
		join

注意px_tr_img一定不能申明为队列,因为是并行,而队列中如果前一个元素没有创建,后一个元素是不能创建的,所以px_tr_img只能是定数组或动态数组。(提醒自己)

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-03-16 22:07:36  更:2022-03-16 22:11:09 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 9:05:11-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码