Data Layout Formats

A data layout format describes how a multi-dimensional tensor is stored in the memory in deep learning.

Common data layout formats include ND, NHWC, and NCHW, which assign specific service semantics to each axis of a tensor.

In addition to the NHWC and NCHW formats, there are several special proprietary data formats, such as FRACTAL_NZ (NZ for short), NC1HWC0, FRACTAL_Z, NDC1HWC0, and FRACTAL_Z_3D. These formats are introduced to meet the high-performance compute requirements of the Cube Unit in the AI Core. By optimizing the memory layout, these formats can improve the computational efficiency. Their specific applications can be observed when you develop related operators using cube multiplication and convolution APIs.

Common Formats

Special Formats for Cube Multiplication

When the Mmad basic API is used to perform cube multiplication, the input and output data formats of the cubes must meet certain requirements. As shown in the following figures, cube A (in L0A Buffer) must be in FRACTAL_ZZ format, cube B (in L0B Buffer) must be in FRACTAL_ZN format, and cube C (in L0C Buffer) must be in FRACTAL_NZ format. These formats divide a cube into fractals (Fractal Matrix), aligning with the hardware feature that the Cube Unit reads (16, 16) × (16, 16) data for computation each time (using the half data type as an example), thereby improving the cube computation efficiency. The size of a fractal is related to the data type and the storage location. For details, please refer to the following description.

  • FRACTAL_NZ/NZ

    The FRACTAL_NZ (NZ for short) format is obtained by performing padding, reshaping, and transposing operations on the two lowest dimensions of a tensor (where higher-order dimensions are on the left and lower-order dimensions on the right). The following shows the conversion process:

    A cube of size (M, N) is divided into M1 × N1 fractals, which are arranged in column-major order, forming an N-shaped pattern. Each fractal contains M0 × N0 elements, which are arranged in row-major order, forming a Z-shaped pattern. That is why this data format is called the NZ format. (M0, N0) indicates the size of a fractal.

    The formula is as follows:

    (..., B, M, N)->pad->(..., B, M1 * M0, N1 * N0)->reshape->(..., B, M1, M0, N1, N0)->transpose->(..., B, N1, M1, M0, N0)

    Generally, the NZ format is used in different scenarios in L0C Buffer and L1 Buffer.

    • In L0C Buffer, the NZ format is used to store the results of cube multiplication. Each fractal has a shape of 16 × 16, containing 256 elements. This structure is ideal for the Cube Unit to perform efficient cube multiplication.
    • In L1 Buffer, the NZ format is adopted to facilitate the conversion to the corresponding ZZ and ZN formats when data is moved to L0A Buffer and L0B Buffer. In this case, the fractal shape is 16 × (32B/sizeof(Datatype)), with a size of 512 bytes.

    Therefore, when data is moved from L0C Buffer to L1 Buffer, the fractal size may change.

    The following example describes how the ND format is converted to the NZ format.

    The shape of the original tensor is (20, 28).

    1
    2
    3
    4
    data = [x for x in range(20 * 28)]
    data_a = data * np.ones((20 * 28), dtype="float16")
    tensor_a = data_a.reshape((20, 28))
    print(tensor_a)
    

    The original tensor data is printed as follows:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    [[  0.   1.   2.   3.   4.   5.   6.   7.   8.   9.  10.  11.  12.  13.
       14.  15.  16.  17.  18.  19.  20.  21.  22.  23.  24.  25.  26.  27.]
     [ 28.  29.  30.  31.  32.  33.  34.  35.  36.  37.  38.  39.  40.  41.
       42.  43.  44.  45.  46.  47.  48.  49.  50.  51.  52.  53.  54.  55.]
     [ 56.  57.  58.  59.  60.  61.  62.  63.  64.  65.  66.  67.  68.  69.
       70.  71.  72.  73.  74.  75.  76.  77.  78.  79.  80.  81.  82.  83.]
     [ 84.  85.  86.  87.  88.  89.  90.  91.  92.  93.  94.  95.  96.  97.
       98.  99. 100. 101. 102. 103. 104. 105. 106. 107. 108. 109. 110. 111.]
     [112. 113. 114. 115. 116. 117. 118. 119. 120. 121. 122. 123. 124. 125.
      126. 127. 128. 129. 130. 131. 132. 133. 134. 135. 136. 137. 138. 139.]
     [140. 141. 142. 143. 144. 145. 146. 147. 148. 149. 150. 151. 152. 153.
      154. 155. 156. 157. 158. 159. 160. 161. 162. 163. 164. 165. 166. 167.]
     [168. 169. 170. 171. 172. 173. 174. 175. 176. 177. 178. 179. 180. 181.
      182. 183. 184. 185. 186. 187. 188. 189. 190. 191. 192. 193. 194. 195.]
     [196. 197. 198. 199. 200. 201. 202. 203. 204. 205. 206. 207. 208. 209.
      210. 211. 212. 213. 214. 215. 216. 217. 218. 219. 220. 221. 222. 223.]
     [224. 225. 226. 227. 228. 229. 230. 231. 232. 233. 234. 235. 236. 237.
      238. 239. 240. 241. 242. 243. 244. 245. 246. 247. 248. 249. 250. 251.]
     [252. 253. 254. 255. 256. 257. 258. 259. 260. 261. 262. 263. 264. 265.
      266. 267. 268. 269. 270. 271. 272. 273. 274. 275. 276. 277. 278. 279.]
     [280. 281. 282. 283. 284. 285. 286. 287. 288. 289. 290. 291. 292. 293.
      294. 295. 296. 297. 298. 299. 300. 301. 302. 303. 304. 305. 306. 307.]
     [308. 309. 310. 311. 312. 313. 314. 315. 316. 317. 318. 319. 320. 321.
      322. 323. 324. 325. 326. 327. 328. 329. 330. 331. 332. 333. 334. 335.]
     [336. 337. 338. 339. 340. 341. 342. 343. 344. 345. 346. 347. 348. 349.
      350. 351. 352. 353. 354. 355. 356. 357. 358. 359. 360. 361. 362. 363.]
     [364. 365. 366. 367. 368. 369. 370. 371. 372. 373. 374. 375. 376. 377.
      378. 379. 380. 381. 382. 383. 384. 385. 386. 387. 388. 389. 390. 391.]
     [392. 393. 394. 395. 396. 397. 398. 399. 400. 401. 402. 403. 404. 405.
      406. 407. 408. 409. 410. 411. 412. 413. 414. 415. 416. 417. 418. 419.]
     [420. 421. 422. 423. 424. 425. 426. 427. 428. 429. 430. 431. 432. 433.
      434. 435. 436. 437. 438. 439. 440. 441. 442. 443. 444. 445. 446. 447.]
     [448. 449. 450. 451. 452. 453. 454. 455. 456. 457. 458. 459. 460. 461.
      462. 463. 464. 465. 466. 467. 468. 469. 470. 471. 472. 473. 474. 475.]
     [476. 477. 478. 479. 480. 481. 482. 483. 484. 485. 486. 487. 488. 489.
      490. 491. 492. 493. 494. 495. 496. 497. 498. 499. 500. 501. 502. 503.]
     [504. 505. 506. 507. 508. 509. 510. 511. 512. 513. 514. 515. 516. 517.
      518. 519. 520. 521. 522. 523. 524. 525. 526. 527. 528. 529. 530. 531.]
     [532. 533. 534. 535. 536. 537. 538. 539. 540. 541. 542. 543. 544. 545.
      546. 547. 548. 549. 550. 551. 552. 553. 554. 555. 556. 557. 558. 559.]]
    

    The conversion process is expressed by pseudocode as follows:

    N0 = 16
    N1 = (28 + N0 - 1) // N0
    pad_n = N1 * N0 - 28
    M0 = 16
    M1 = (20 + M0 - 1) // M0
    pad_m = M1 * M0 - 20
    tensor_b = np.pad(tensor_a, [[0, pad_m], [0, pad_n]])
    tensor_b = tensor_b.reshape((M1, M0, N1, N0))
    tensor_b = tensor_b.transpose((2, 0, 1, 3))
    print(tensor_b)

    The following figure shows the conversion process.

    After the conversion, the tensor is printed as follows:

    [[[[  0.   1.   2. ...  13.  14.  15.]
       [ 28.  29.  30. ...  41.  42.  43.]
       [ 56.  57.  58. ...  69.  70.  71.]
       ...
       [364. 365. 366. ... 377. 378. 379.]
       [392. 393. 394. ... 405. 406. 407.]
       [420. 421. 422. ... 433. 434. 435.]]
    
      [[448. 449. 450. ... 461. 462. 463.]
       [476. 477. 478. ... 489. 490. 491.]
       [504. 505. 506. ... 517. 518. 519.]
       ...
       [  0.   0.   0. ...   0.   0.   0.]
       [  0.   0.   0. ...   0.   0.   0.]
       [  0.   0.   0. ...   0.   0.   0.]]]
    
    
     [[[ 16.  17.  18. ...   0.   0.   0.]
       [ 44.  45.  46. ...   0.   0.   0.]
       [ 72.  73.  74. ...   0.   0.   0.]
       ...
       [380. 381. 382. ...   0.   0.   0.]
       [408. 409. 410. ...   0.   0.   0.]
       [436. 437. 438. ...   0.   0.   0.]]
    
      [[464. 465. 466. ...   0.   0.   0.]
       [492. 493. 494. ...   0.   0.   0.]
       [520. 521. 522. ...   0.   0.   0.]
       ...
       [  0.   0.   0. ...   0.   0.   0.]
       [  0.   0.   0. ...   0.   0.   0.]
       [  0.   0.   0. ...   0.   0.   0.]]]]

Special Formats for Convolution

Formats Related to Matmul High-Level APIs

COLUMN_MAJOR

The ND data layout format is also called ROW_MAJOR, and there is a counterpart called COLUMN_MAJOR. The difference between these two formats lies in the direction in which consecutive elements in an array or cube are stored contiguously.

The following figure shows these two data layout formats.