自动化 tikzpicture 重现类似矩阵的图像

自动化 tikzpicture 重现类似矩阵的图像

我想用 tikz 复制这张图片

在此处输入图片描述

我的主要问题是正确的,因为我想利用 tikz 的自动功能进行绘图。截至目前,这平均能量损失是我最好的尝试:

\documentclass[]{standalone}
\usepackage{tikz}
\usetikzlibrary{arrows,positioning}
\usetikzlibrary{calc}
\tikzset{%
    controlcpu/.pic={
        \node[fill=yellow,      
            label={[anchor=north, 
                        name=cu]90:Control Unit}, 
            minimum width=3cm, 
            minimum height=2.5cm, 
            draw] (CU) {};
},
    controlgpu/.pic={
        \node[fill=yellow,       
            minimum width=3mm, 
            minimum height=1mm,
            draw] (CU) {};
},
    cachecpu/.pic={
        \node[fill=red,      
            label={[anchor=north, 
                        name=cache]90:Cache}, 
            minimum width=3cm, 
            minimum height=2.5cm, 
            draw] (CU) {};
},
    cachegpu/.pic={
        \node[fill=red,       
            minimum width=3mm, 
            minimum height=1mm, 
            draw] (CUGPU) {};
},
    alucpu/.pic={
        \node[fill=green,      
            label={[anchor=north, 
                        name=alu]90:ALU}, 
            minimum width=3cm, 
            minimum height=2.5cm, 
            draw] (ALUCPU) {};
},
    alugpu/.pic={
        \node[fill=green,      
            minimum width=0.3cm, 
            minimum height=0.2cm, 
            draw] (ALUGPU) {};
},
    dram/.pic={
        \node[fill=orange,      
            label={[anchor=north, 
                        name=dr]90:DRAM}, 
            minimum width=3cm, 
            minimum height=2.5cm, 
            draw] (DRAM) {};
}
}

\begin{document}
\begin{tikzpicture}

\matrix[] (GRID) [column sep=1mm, row sep=1mm]
{\pic{controlgpu}; & \pic{cachegpu}; & \pic{alugpu}; & \pic{alugpu}; & \pic{alugpu}; & \pic{alugpu};  \pic{alugpu}; & \pic{alugpu};  \pic{alugpu}; & \pic{alugpu};  \pic{alugpu}; & \pic{alugpu};  \pic{alugpu}; & \pic{alugpu};  \pic{alugpu}; & \pic{alugpu}; & \pic{alugpu}; & \pic{alugpu}; \\
\pic{controlgpu}; & \pic{cachegpu}; & \pic{alugpu}; & \pic{alugpu}; & \pic{alugpu}; & \pic{alugpu};  \pic{alugpu}; & \pic{alugpu};  \pic{alugpu}; & \pic{alugpu};  \pic{alugpu}; & \pic{alugpu};  \pic{alugpu}; & \pic{alugpu};  \pic{alugpu}; & \pic{alugpu}; & \pic{alugpu}; & \pic{alugpu}; \\};

\end{tikzpicture}

\end{document}

这很丑陋,输出也很糟糕,因为我不知道如何把一个放在controlgpu另一个cachegpu之上

在此处输入图片描述

此外,我无法利用foreach:也许是因为它需要“位置”(节点)方法?

我有两个问题

  • 使用什么最有效的方法来重现它tikz 的矩阵
  • 可以使用吗foreachforeach推荐用于此类绘图吗?

例如,这里在官方指南中我的意思是使用来foreach生成类似矩阵形状的 tikzfigure。

答案1

对于右图(GPU):

在此处输入图片描述

细胞由双环驱动:

\documentclass[tikz,
               margin=3mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{arrows,
                calc,
                chains,         % <-- added
                positioning,
                shapes.multipart% <-- added
                }

\begin{document}
    \begin{tikzpicture}[
    node distance = 0.5mm and 0.5mm,
      start chain = going right,
every node/.style = {on chain, inner sep=0pt, outer sep=0pt},
YO/.style = {% Yellow Orange boxes
    rectangle split, rectangle split parts=2, draw,
    rectangle split part fill = {yellow,red},
    rectangle split empty part height=2mm-\pgflinewidth, 
    minimum width=4mm, 
    node contents={\nodepart{one}\nodepart{two}}},
 G/.style = {% Green boxes
    draw, fill=green!80, minimum size=4mm, 
    node contents={}},
 O/.style = {% Orange boxes
    draw, fill=orange,  
    inner ysep=3mm, inner xsep=4mm, align=left,
    node contents={DRAM}},
                    ]
\node (n11) [YO];
\foreach \i in {2,3,...,16}
\node (n1\i) [G];
% other rows
\foreach \j [count=\jx from 1] in {2,3,...,8}
{
\node (n\j1) [YO,below=of n\jx1];
\foreach \i in {2,3,...,16}
\node (n2\i) [G];
}

% dram
\path   let \p1=($(n11.west)-(n116.east)$),
            \n1={veclen(\y1,\x1)} in
        node[below right=0.5 mm and 0 mm of n81.south west,
             text width=\n1-8mm, 
             O, label={[inner sep=1mm]below:GPU}];
    \end{tikzpicture}
\end{document}

类似地,也可以为 CPU 绘制左图。

答案2

在此处输入图片描述

\documentclass[border=2mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\newcommand\unit[4]   {\draw[fill=#2] (#4) rectangle +(#1);
                       \node[font=\sffamily\bfseries] at ($(#4)+0.5*(#1)$) {#3};
                      }
\newcommand\gpualu    {\unit{ 0.9,0.9 }{green!30}{}}
\newcommand\gpucontrol{\unit{ 0.9,0.4 }{yellow!30}{}}
\newcommand\gpucache  {\unit{ 0.9,0.4 }{red!30}{}}
\newcommand\dram      {\unit{16.9,1.9 }{red!30}{DRAM}}
\newcommand\cpualu    {\unit{ 4.1,2.05}{green!30}{ALU}}
\newcommand\cpucontrol{\unit{ 8.4,4.2 }{yellow!30}{Control}}
\newcommand\cpucache  {\unit{16.9,4.2 }{red!30}{Cache}}
\begin{document}
\begin{tabular}[b]{c}
\begin{tikzpicture}[scale=0.4]
  \dram      { 0  ,-2.5}
  \cpucache  { 0  , 0}
  \cpucontrol{ 0  ,4.4}
  \cpualu    { 8.6,4.4}
  \cpualu    {12.8,4.4}
  \cpualu    { 8.6,6.55}
  \cpualu    {12.8,6.55}
  \node[font=\sffamily\bfseries] at (8.45,-3.5) {CPU};
\end{tikzpicture}\\
Central Processing Unit (CPU)
\end{tabular}
\qquad
\begin{tabular}[b]{c}
\begin{tikzpicture}[scale=0.4]
  \dram{0,-2.5}
  \foreach \i in {0,...,7}
    \gpucontrol{0,1.1*\i+0.5}
    \gpucache{0,1.1*\i}
    \foreach \j in {1,...,16}
      \gpualu{\j,1.1*\i};
  \node[font=\sffamily\bfseries] at (8.45,-3.5) {GPU};
\end{tikzpicture}\\
Graphical Processing Unit (GPU)
\end{tabular}
\end{document}

编辑:关于我如何进行的一些解释。

  1. 相对或绝对定位:灵活的解决方案是将元素相对于彼此定位,从不指定任何坐标。缺点是您必须指定距离、组项等参数,这可能需要在文档中进行多次查找,并且可能变得不透明。对于这种独一无二的绘图,我选择了绝对定位方法,因为它保证更快、更紧凑。

  2. 主要结构是一个填充的矩形,偶尔带有标签。这就是它的\node[size,color] at (position) {label}作用。出于tikz某些原因size,和position并不被同等对待:position可以是无量纲的并且可以缩放,size需要单位并且不缩放。由于此类绘图首先要绘制在某个方便的网格中,然后缩放到所需的大小,因此我必须将\draw矩形缩放到:

    \draw[fill=#2] (#4) rectangle +(#1); % #2 fill color, #4 coordinates left bottom corner, #1 size = width,height
    

    仅用于\node将标签定位在中心。

    \node at ($(#4)+0.5*(#1)$) {#3}; % #4 coordinates of left bottom corner, #1 vector to the top right corner, #3 label
    

    该表达式$(#4)+0.5*(#1)$将矩形中心的坐标计算为“左下角加上到右上角距离的一半”。此坐标计算需要\usetikzlibrary{calc}在序言中说明。

  3. 我选择网格的左下角作为原点(0,0),然后从那里开始上下移动。我选择 1×1 的正方形作为基本单位。为了分离 GPU-ALU,我选择给它们一个大小0.9,0.9。后来我想在行之间留出更多空间,所以我在循环中为 y 坐标引入了因子 1.1 \foreach

相关内容