![在这个 TikZ 示例中,如何进行叠加并解决线条绘制问题?](https://linux22.com/image/240998/%E5%9C%A8%E8%BF%99%E4%B8%AA%20TikZ%20%E7%A4%BA%E4%BE%8B%E4%B8%AD%EF%BC%8C%E5%A6%82%E4%BD%95%E8%BF%9B%E8%A1%8C%E5%8F%A0%E5%8A%A0%E5%B9%B6%E8%A7%A3%E5%86%B3%E7%BA%BF%E6%9D%A1%E7%BB%98%E5%88%B6%E9%97%AE%E9%A2%98%EF%BC%9F.png)
我正在处理一张图片(代码如下),却遇到了两个问题:
- 从 DRAM 到 GPGPU 的线路连接不正确。此外,在重新生成图片时,DRAM 和 GPGPU 会分开。我该如何解决这个问题?
- 从 GPGPU 到集群的“缩放”线穿过集群。如何让集群“位于”缩放线之上?
下面是它当前的样子(由于问题 1 中描述的 DRAM 的不断移动,缩放线看起来很混乱):
如果有人能帮助我,我将不胜感激。
\documentclass[a4paper, 11pt]{article}
% Load packages
\usepackage{tikz}
\usepackage[sc,osf]{mathpazo}
% Load TikZ libraries
\usetikzlibrary{shapes,arrows}
\usetikzlibrary{fit}
\usetikzlibrary{backgrounds}
\usetikzlibrary{positioning}
\usetikzlibrary{calc}
% Define colors
\definecolor{lightGrey}{rgb}{0.9, 0.9, 0.9}
\definecolor{shade0}{named}{white}
\definecolor{shade1}{named}{lightGrey}
\definecolor{shade2}{rgb}{0.8, 0.8, 0.8}
\definecolor{shade3}{rgb}{0.65, 0.65, 0.65}
\definecolor{shade4}{rgb}{0.45, 0.45, 0.45}
% Text settings
\newcommand{\figureTextSize}{\tiny}
% Figure element lengths
\newlength{\gpgpuElemSize}
\setlength{\gpgpuElemSize}{8mm}
\newlength{\gpgpuElemSep}
\setlength{\gpgpuElemSep}{1mm}
% TikZ styles
\newcommand{\arrowStyle}{stealth}
\newcommand{\lineThickness}{semithick}
\tikzstyle{box} = [%
draw,
rectangle,
\lineThickness,
]
\begin{document}
\begingroup
\figureTextSize
\newcommand{\drawSM}{%
\begin{tikzpicture}[remember picture]
% SPs
\foreach \y in {1, ..., 4} {%
\foreach \x in {1, ..., 2} {%
\ifnum \x=1
\ifnum \y=1
\node [sp] (sp\y-\x) {SP};
\else
\pgfmathtruncatemacro\prevY{\y-1}
\node [sp, below=of sp\prevY-\x] (sp\y-\x) {SP};
\fi
\else
\pgfmathtruncatemacro\prevX{\x-1}
\node [sp, right=of sp\y-\prevX] (sp\y-\x) {SP};
\fi
}
}
% SFUs
\foreach \i in {1, ..., 2} {%
\ifnum \i=1
\path let \p1 = (sp1-1.south west),
\p2 = (sp1-2.north east)
in
node [%
sfu,
minimum width=\x2-\x1-\pgflinewidth,
below right,
] at ([%
yshift={-0.5\gpgpuElemSep},
] sp4-1.south west) (sfu\i) {SFU};
\else
\pgfmathtruncatemacro\prevI{\i-1}
\path let \p1 = (sp1-1.south west),
\p2 = (sp1-2.north east)
in
node [%
sfu,
minimum width=\x2-\x1-\pgflinewidth,
below=of sfu\prevI,
] (sfu\i) {SFU};
\fi
}
% Fetch/Dispatch
\node [issuer, right=of sp1-2] (issuer) {Fetch/Dispatch};
% Register file
\node [register, below=of issuer] (register) {Registers};
% Instruction cache
\node [cache, below=of register] (icache) {Inst. cache};
% Constant cach
\node [cache, below=of icache] (ccache) {Constant cache};
% Shared memory
\path let \p1 = (sfu2.south west),
\p2 = (sfu1.north east),
\p3 = (ccache.south west),
\p4 = (ccache.north east)
in
node [%
memory,
minimum width=\x4-\x3-\pgflinewidth,
minimum height=\y2-\y1-\pgflinewidth,
below=of ccache,
] (sharedmem) {%
\begin{tabular}{c}
Shared \\
memory
\end{tabular}
};
\end{tikzpicture}
}
\begin{tikzpicture}[%
auto,
>=\arrowStyle,
remember picture,
every node/.style={%
node distance=0.5\gpgpuElemSep,
},
splitted/.style={%
rectangle split,
rectangle split parts=2,
rectangle split draw splits=false,
},
gpgpu/.style={%
box,
fill=shade2,
splitted,
},
gpgpu-part/.style={%
box,
fill=shade3,
minimum size=10mm,
},
dram/.style={%
box,
fill=shade1,
minimum width=8mm,
minimum height=5mm,
node distance=\gpgpuElemSep,
},
connection/.style={%
<->,
\lineThickness,
},
cluster/.style={%
box,
fill=shade3,
splitted,
},
sm/.style={%
cluster,
fill=shade0,
},
sp/.style={%
box,
fill=shade1,
minimum size=0.5\gpgpuElemSize,
inner sep=0pt,
},
sfu/.style={%
sp,
},
register/.style={%
box,
fill=shade2,
minimum height=0.5\gpgpuElemSize,
minimum width=2\gpgpuElemSize,
inner sep=0pt,
},
cache/.style={%
register,
},
memory/.style={%
register,
},
issuer/.style={%
register,
fill=shade3,
},
zoom-line/.style={%
\lineThickness,
dashed,
},
]
\node (all-parts) {%
\begin{tikzpicture}[remember picture]
% GPGPU - zoomed out
\node [gpgpu] (gpgpu) {%
GPGPU
\nodepart{two}
\begin{tikzpicture}[remember picture]
% Clusters
\foreach \y in {1, ..., 3} {%
\foreach \x in {1, ..., 4} {%
\ifnum \x=1
\ifnum \y=1
\node [gpgpu-part] (gp\y-\x) {};
\else
\pgfmathtruncatemacro\prevY{\y-1}
\node [gpgpu-part, below=of gp\prevY-\x] (gp\y-\x) {};
\fi
\else
\pgfmathtruncatemacro\prevX{\x-1}
\node [gpgpu-part, right=of gp\y-\prevX] (gp\y-\x) {};
\fi
}
}
\end{tikzpicture}
};
% DRAMs
\node [below=of gpgpu, yshift=-2\gpgpuElemSep] {%
\begin{tikzpicture}[remember picture]
\foreach \i in {1, ..., 5} {%
\ifnum \i=1
\node [dram] (dram\i) {DRAM};
\else
\pgfmathtruncatemacro\prevI{\i-1}
\node [dram, right=of dram\prevI] (dram\i) {DRAM};
\fi
% Connect DRAM with GPGPU
\draw [connection] (dram\i) -- (dram\i |- gpgpu.south);
}
\end{tikzpicture}
};
\end{tikzpicture}
};
% Cluster - in detail
\node [cluster, right=of all-parts, xshift=4\gpgpuElemSep] (cluster-big) {%
Cluster
\nodepart{two}
\begin{tikzpicture}[remember picture]
% SMs
\node [sm] (sm1) {SM \nodepart{two}\drawSM};
\node [sm, right=of sm1] (sm2) {SM \nodepart{two}\drawSM};
% Texture memory
\path let \p1 = (sm1.south west),
\p2 = (sm2.north east)
in
node [%
memory,
minimum width=\x2-\x1-\pgflinewidth,
below right,
] at ([%
yshift={-0.5\gpgpuElemSep},
] sm1.south west) (texturemem) {Texture memory};
\end{tikzpicture}
};
% Zoom lines
\draw [zoom-line] (gp2-4.north west) -- (cluster-big.north west);
\draw [zoom-line] (gp2-4.north east) -- (cluster-big.north east);
\draw [zoom-line] (gp2-4.south west) -- (cluster-big.south west);
\draw [zoom-line] (gp2-4.south east) -- (cluster-big.south east);
\end{tikzpicture}
\endgroup
\end{document}
答案1
1)画出节点外的连接线。
2)可以使用层,将集群节点放在层中foreground
,其余所有节点都放在main
层中。
\documentclass[a4paper, 11pt]{article}
% Load packages
\usepackage{tikz}
\usepackage[sc,osf]{mathpazo}
% Load TikZ libraries
\usetikzlibrary{shapes,arrows}
\usetikzlibrary{fit}
\usetikzlibrary{backgrounds}
\usetikzlibrary{positioning}
\usetikzlibrary{calc}
% Define colors
\definecolor{lightGrey}{rgb}{0.9, 0.9, 0.9}
\definecolor{shade0}{named}{white}
\definecolor{shade1}{named}{lightGrey}
\definecolor{shade2}{rgb}{0.8, 0.8, 0.8}
\definecolor{shade3}{rgb}{0.65, 0.65, 0.65}
\definecolor{shade4}{rgb}{0.45, 0.45, 0.45}
% Text settings
\newcommand{\figureTextSize}{\tiny}
% Figure element lengths
\newlength{\gpgpuElemSize}
\setlength{\gpgpuElemSize}{8mm}
\newlength{\gpgpuElemSep}
\setlength{\gpgpuElemSep}{1mm}
% TikZ styles
\newcommand{\arrowStyle}{stealth}
\\
newcommand{\lineThickness}{semithick}
\tikzstyle{box} = [%
draw,
rectangle,
\lineThickness,
]
\begin{document}
\pgfdeclarelayer{background}
\pgfdeclarelayer{foreground}
\pgfsetlayers{background,main,foreground}
\begingroup
\figureTextSize
\newcommand{\drawSM}{%
\begin{tikzpicture}[remember picture]
% SPs
\foreach \y in {1, ..., 4} {%
\foreach \x in {1, ..., 2} {%
\ifnum \x=1
\ifnum \y=1
\node [sp] (sp\y-\x) {SP};
\else
\pgfmathtruncatemacro\prevY{\y-1}
\node [sp, below=of sp\prevY-\x] (sp\y-\x) {SP};
\fi
\else
\pgfmathtruncatemacro\prevX{\x-1}
\node [sp, right=of sp\y-\prevX] (sp\y-\x) {SP};
\fi
}
}
% SFUs
\foreach \i in {1, ..., 2} {%
\ifnum \i=1
\path let \p1 = (sp1-1.south west),
\p2 = (sp1-2.north east)
in
node [%
sfu,
minimum width=\x2-\x1-\pgflinewidth,
below right,
] at ([%
yshift={-0.5\gpgpuElemSep},
] sp4-1.south west) (sfu\i) {SFU};
\else
\pgfmathtruncatemacro\prevI{\i-1}
\path let \p1 = (sp1-1.south west),
\p2 = (sp1-2.north east)
in
node [%
sfu,
minimum width=\x2-\x1-\pgflinewidth,
below=of sfu\prevI,
] (sfu\i) {SFU};
\fi
}
% Fetch/Dispatch
\node [issuer, right=of sp1-2] (issuer) {Fetch/Dispatch};
% Register file
\node [register, below=of issuer] (register) {Registers};
% Instruction cache
\node [cache, below=of register] (icache) {Inst. cache};
% Constant cach
\node [cache, below=of icache] (ccache) {Constant cache};
% Shared memory
\path let \p1 = (sfu2.south west),
\p2 = (sfu1.north east),
\p3 = (ccache.south west),
\p4 = (ccache.north east)
in
node [%
memory,
minimum width=\x4-\x3-\pgflinewidth,
minimum height=\y2-\y1-\pgflinewidth,
below=of ccache,
] (sharedmem) {%
\begin{tabular}{c}
Shared \\
memory
\end{tabular}
};
\end{tikzpicture}
}
\begin{tikzpicture}[%
auto,
>=\arrowStyle,
remember picture,
every node/.style={%
node distance=0.5\gpgpuElemSep,
},
splitted/.style={%
rectangle split,
rectangle split parts=2,
rectangle split draw splits=false,
},
gpgpu/.style={%
box,
fill=shade2,
splitted,
},
gpgpu-part/.style={%
box,
fill=shade3,
minimum size=10mm,
},
dram/.style={%
box,
fill=shade1,
minimum width=8mm,
minimum height=5mm,
node distance=\gpgpuElemSep,
},
connection/.style={%
<->,
\lineThickness,
},
cluster/.style={%
box,
fill=shade3,
splitted,
},
sm/.style={%
cluster,
fill=shade0,
},
sp/.style={%
box,
fill=shade1,
minimum size=0.5\gpgpuElemSize,
inner sep=0pt,
},
sfu/.style={%
sp,
},
register/.style={%
box,
fill=shade2,
minimum height=0.5\gpgpuElemSize,
minimum width=2\gpgpuElemSize,
inner sep=0pt,
},
cache/.style={%
register,
},
memory/.style={%
register,
},
issuer/.style={%
register,
fill=shade3,
},
zoom-line/.style={%
\lineThickness,
dashed,
},
]
\node (all-parts) {%
\begin{tikzpicture}[remember picture]
% GPGPU - zoomed out
\node [gpgpu] (gpgpu) {%
GPGPU
\nodepart{two}
\begin{tikzpicture}[remember picture]
% Clusters
\foreach \y in {1, ..., 3} {%
\foreach \x in {1, ..., 4} {%
\ifnum \x=1
\ifnum \y=1
\node [gpgpu-part] (gp\y-\x) {};
\else
\pgfmathtruncatemacro\prevY{\y-1}
\node [gpgpu-part, below=of gp\prevY-\x] (gp\y-\x) {};
\fi
\else
\pgfmathtruncatemacro\prevX{\x-1}
\node [gpgpu-part, right=of gp\y-\prevX] (gp\y-\x) {};
\fi
}
}
\end{tikzpicture}
};
% DRAMs
\node [below=of gpgpu, yshift=-2\gpgpuElemSep] {%
\begin{tikzpicture}[remember picture]
\foreach \i in {1, ..., 5} {%
\ifnum \i=1
\node [dram] (dram\i) {DRAM};
\else
\pgfmathtruncatemacro\prevI{\i-1}
\node [dram, right=of dram\prevI] (dram\i) {DRAM};
\fi
}
\end{tikzpicture}
};
\end{tikzpicture}
};
% Connect DRAM with GPGPU
\foreach \i in {1, ..., 5} %
\draw [connection] (dram\i) -- (dram\i |- gpgpu.south);
% Cluster - in detail
\begin{pgfonlayer}{foreground}
\node [cluster, right=of all-parts, xshift=4\gpgpuElemSep] (cluster-big) {%
Cluster
\nodepart{two}
\begin{tikzpicture}[remember picture]
% SMs
\node [sm] (sm1) {SM \nodepart{two}\drawSM};
\node [sm, right=of sm1] (sm2) {SM \nodepart{two}\drawSM};
% Texture memory
\path let \p1 = (sm1.south west),
\p2 = (sm2.north east)
in
node [%
memory,
minimum width=\x2-\x1-\pgflinewidth,
below right,
] at ([%
yshift={-0.5\gpgpuElemSep},
] sm1.south west) (texturemem) {Texture memory};
\end{tikzpicture}
};
\end{pgfonlayer}
% Zoom lines
\draw [zoom-line] (gp2-4.north west) -- (cluster-big.north west);
\draw [zoom-line] (gp2-4.north east) -- (cluster-big.north east);
\draw [zoom-line] (gp2-4.south west) -- (cluster-big.south west);
\draw [zoom-line] (gp2-4.south east) -- (cluster-big.south east);
\end{tikzpicture}
\endgroup
\end{document}
答案2
请记住,TeX.tex
每次解析文档的一行。因此,您在 中提供命令的顺序tikzpicture
将提供一个层次结构,图形元素最终将在该层次结构中排版。为此,在回答您的第二个问题时(无需更正提供的代码),您需要将 移到Zoom lines
之前Cluster
(在GPGPU
和之间Cluster
)。这可能需要您重新编码部分(全部?)Cluster
或使用不同的技术来获取cluster-big.<location>
节点。
另一种不太优雅的方法是将整个内容排版Cluster
两次。第二次是在打印之后Zoom lines
。