ãã®èšäºã¯ã NTT docomo Business Advent Calendar 2025 19æ¥ç®ã®èšäºã§ãã ããã«ã¡ã¯ãã€ãããŒã·ã§ã³ã»ã³ã¿ãŒã®éŽã¶å¶ºã§ããæ®æ®µã¯AIã¢ã¯ã»ã©ã¬ãŒã¿ã®æ€èšŒã«é¢ããæ¥åã«åŸäºããŠããŸãã æ¬èšäºã§ã¯ããŸãTenstorrentã®AIã¢ã¯ã»ã©ã¬ãŒã¿ã¢ãŒããã¯ãã£ã玹ä»ãããã®ç¹åŸŽã«ã€ããŠèª¬æããŸããæ¬¡ã«ãè€æ°ã®æŒç®ã1ã€ã®kernelã«çµ±åããfused kernelã«ããæé©åã«æ³šç®ããæšæºæ£èŠä¹±æ°(randn)ãäŸã«Tenstorrentã®ã¢ã¯ã»ã©ã¬ãŒã¿ã«ãããå
·äœçãªå®è£
æ¹æ³ãšæ§èœè©äŸ¡ãå
±æããŸãããã®çµæãåŸæ¥ã®æŒç®ã®çµã¿åããã®æšæºæ£èŠä¹±æ°ã®å®è£
ãšæ¯èŒããŠãfused kernelå®è£
ã«ããçŽ4åã®é«éåã確èªããŸããã Tenstorrentãšã¯ ãªã³ãããèšç®ã掻ãããFlash Attention fused kernelã®å®è£
ãšè©äŸ¡ å®è£
æ§èœè©äŸ¡ ãŸãšã Tenstorrentãšã¯ Tenstorrent Inc. ã¯æ¬¡äžä»£AIã¢ã¯ã»ã©ã¬ãŒã¿ã補é ããåå°äœã¡ãŒã«ãŒã§ãã ãªãŒãã³æŠç¥ãæ²ããŠãããã¢ã¯ã»ã©ã¬ãŒã¿ã«ã¯RISC-Vãæ¡çšãããœãããŠã§ã¢ã«é¢ããŠã¯OSS ( https://github.com/tenstorrent ) ãšããŠç©æ¥µçã«å
¬éãããŠããŸãã 2025幎12æçŸåšã§ã¯DECãAMDãAppleãTeslaãæŽä»»ããåå°äœæ¥çã®èåãªJim Kelleræ°ãCEOãåããŠããŸãã Tenstorrentã®AIã¢ã¯ã»ã©ã¬ãŒã¿ã®ã¢ãŒããã¯ãã£ã«ã€ããŠç޹ä»ããŸãã åŒçš: https://speakerdeck.com/tenstorrent_japan/tensix-core-akitekutiyajie-shuo?slide=7 ã¢ã¯ã»ã©ã¬ãŒã¿ã¯Tensix CoreãšåŒã°ãã5ã€ã®Baby RISC-Vã2ã€ã®Network-on-Chip(NoC)ãSRAMã§æ§æããããã®ãè€æ°æèŒãããŠããŸãã äžè¬çãªããŒããŠã§ã¢ç®¡çãã£ãã·ã¥ãæããªãæ§æãšãªã£ãŠãããæç€ºçã«ã³ã¢ä»è¿ã®SRAMãæäœãã忣ã¡ã¢ãªåã®Near Memory Computing(NMC)ãªèšèšã§ãã 5ã€ã®RISC-Vã³ã¢ã¯ç¬ç«ãªåäœãå¯èœãªMIMD(Multiple Instructionã Multiple Data)ã¢ãŒããã¯ãã£ã§ãã å€ãã®åŠçã¯å
žåçã«ã¯ããŒã¿èªã¿åºããè¡ãReader kernel(RISC-V 1)ã èšç®ãããCompute kernel(RISC-V 2ã 3ã 4)ã ããŒã¿æžã蟌ã¿ãè¡ãWriter kernel(RISC-V 5)ã«åããŠå®è¡ãããŸãã åŸè¿°ããæšæºæ£èŠä¹±æ°ã®fused kernelå®è£
ã§ã¯ããŒã¿èªã¿èŸŒã¿ãäžèŠã®ããComputeãWriter kernelã®ã¿ã®å®è£
ãšãªã£ãŠãããåŠçã«åãããŠèªç±åºŠãé«ã調æŽã§ããŸãã 16x16ãåºæ¬ãšããŠtileããŒã¹ã®æŒç®ãšã³ãžã³ãç©ãã§ãããCompute kernelã¯ãã®ãšã³ãžã³ãåŒã³åºããŸãã kerneléã®ããŒã¿ã¯Circular Buffer (CB)ãšåŒã°ããSRAMäžã®FIFOãã¥ãŒã§ããåããããŸãã ãã¹ããšã®ããŒã¿äº€æã¯å€åŽã®DRAM(GDDR)ãä»ããŠè¡ãããŸãã ãã®ä»ã®æè¡è©³çŽ°ã¯æ¥æ¬æ³äººã®Tenstorrent Japanãã以äžã«ããŸããŸãªè³æãå
¬éãããŠãããããåç
§ãã ããã https://speakerdeck.com/tenstorrent_japan ãªã³ãããèšç®ã掻ãããFlash Attention ã¢ã¯ã»ã©ã¬ãŒã¿ã®ç¹åŸŽãšããŠãäœã³ã¹ãåã®ããã«HBM(High Bandwidth Memory)ãªã©ã®é«ã³ã¹ããªã¡ã¢ãªã䜿ããªãèšèšãšãªã£ãŠããŸãã ãã®ããã§ããã ãDRAMåŸåŸ©ã«ãããªãŒããŒããããé¿ããããã«ããªã³ãããã®SRAMäžã§èšç®ãã工倫ããããŸãã ããã§ã¯LLMã®Attentionèšç®ã®äºäŸãåãäžããŠãã©ã®ããã«Tenstorrentã®AIã¢ã¯ã»ã©ã¬ãŒã¿ã§å¹çåãããã®ãã説æããŸãã https://github.com/tenstorrent/tt-metal/blob/main/tech_reports/FlashAttention/FlashAttention.md LLMã®Attentionã¯ãã®ãŸãŸèšç®ãããšã巚倧ãªäžéè¡åã«ããHBMã DRAMãžã®ããŒã¿ç§»åããªãŒããŒããããšãªãããšãç¥ãããŠãããŸãã FlashAttention 1 2 ã¯ããã®èª²é¡ã«å¯ŸããŠè¡åããã£ã³ã¯ã«åå²ããããé«éãªSRAMäžã§èšç®ãããŒã¿ç§»åã®ãªãŒããŒããããåæžããé«éåããææ³ã§ãã Tenstorrentã®AIã¢ã¯ã»ã©ã¬ãŒã¿ã§ãããã®FlashAttentionãé©çšå¯èœã§ãã 倧容éã®SRAMãå©çšããŠå®è£
ããäžéããŒã¿ãDRAMã«æžã蟌ãŸããªãããé«éåãããŸãã 以äžã®å³ã®ããã«ããŒã¹ã©ã€ã³å®è£
ãšæ¯èŒããŠå¹³åããŠ20åé«éã«åäœããŸãã åŒçš: https://github.com/tenstorrent/tt-metal/blob/main/tech_reports/FlashAttention/images/image3.png fused kernelã®å®è£
ãšè©äŸ¡ AIã¢ã¯ã»ã©ã¬ãŒã¿ã®å®è¡ã¯è€æ°ã®kernelã®å®è¡ã«ãããäžéèšç®çµæã®ã¡ã¢ãªã¢ã¯ã»ã¹ãèµ·åãªãŒããŒãããã課é¡ãšãªããŸãã ããã§è€æ°ã®èšç®åŠçã1ã€ã®kernelã«çµ±åããfused kernelã«ããæ§èœãåäžãããåŠçãããçšããããŸãã äŸãã°LLMã®Attentionãªã©ã¯èšç®ãæé©åããããã«1ã€ã®fused kernelãšããŠå®è£
ãããŠããŸãã ttnn.transformer.scaled_dot_product_attention(input_tensor_q: ttnn.Tensor, input_tensor_k: ttnn.Tensor, input_tensor_v: ttnn.Tensor, *, attn_mask: ttnn.Tensor = None, is_causal: bool = true, scale: float = None, sliding_window_size: int = None, memory_config: ttnn.MemoryConfig = None, program_config: SDPAProgramConfig = None, compute_kernel_config: ttnn.DeviceComputeKernelConfig = None, attention_sink: ttnn.Tensor = None) â ttnn.Tensor https://docs.tenstorrent.com/tt-metal/latest/ttnn/ttnn/api/ttnn.transformer.scaled_dot_product_attention.html#ttnn.transformer.scaled_dot_product_attention ããã§ã¯ttnnã«å®è£
ãããŠããªãæšæºæ£èŠä¹±æ°ãçæããrandnãå®è£
ããŸãã randnã¯äžè¬ç㪠PyTorchã® torch.randn ã Numpyã® np.random.randn ãªã©ã§ã¯ãµããŒããããŠããŸãã æšæºæ£èŠä¹±æ°ã«ã¯ãBox-Mulleræ³ 3 ãçšããŸãã å®è£
æ°èŠã®Operation远å ã¯ã次ã®ããã«æé ã§è¡ããŸãã https://docs.tenstorrent.com/tt-metal/latest/ttnn/ttnn/adding_new_ttnn_operation.html ãŸãããã¹ãåŽã§ã®åŠçãæç²ãããšä»¥äžã®ããã«å®è£
ããŸãã ttnn/cpp/ttnn/operations/randn/device/randn_device_operation.[cpp|hpp] ã§ã¯Operationã®åŒæ°ãããªããŒã·ã§ã³ãå®è£
ããŸãã struct RandnDeviceOperation { struct operation_attributes_t { const ttnn::Shape shape; // ãã³ãœã«ã®åœ¢ç¶ DataType dtype; Layout layout; const MemoryConfig memory_config; MeshDevice* device; const DeviceComputeKernelConfig compute_kernel_config; uint32_t seed; // ä¹±æ°seed }; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void RandnDeviceOperation:: validate_inputs ( const operation_attributes_t& operation_attributes, const tensor_args_t& tensor_args) { TT_FATAL ( operation_attributes.dtype == DataType::FLOAT32 || operation_attributes.dtype == DataType::BFLOAT16, "Randn: Output tensor must be Float32 or Bfloat16" ); // dtypeã«ããããªããŒã·ã§ã³ TT_FATAL (operation_attributes.layout == Layout::TILE, "Randn: Not currently supporting row major layout" ); // ã¡ã¢ãªã¬ã€ã¢ãŠãã®ããªããŒã·ã§ã³ } ã¢ã¯ã»ã©ã¬ãŒã¿äžã®kernelå®è¡ã®è©³çŽ°ã¯ ttnn/cpp/ttnn/operations/randn/device/randn_program_factory.cpp ã«èšè¿°ããŸãã ãŠãŒãã£ãªãã£é¢æ° tt::tt_metal::split_work_to_cores 4 ã«ããã³ã¢ããšã®åŠçãåçã«åæ£ CreateCircularBuffer ã«ããCB(FIFOãã¥ãŒ)ã®äœæ CreateKernel ã«ããComputeã Writer kernelã®äœæ SetRuntimeArgs kernelå®è¡ã®åŒæ°ã®èšå® // split_work_to_coresã«ãããããããã®ã³ã¢ã«åŠçãå²ãæ¯ã auto [num_cores, all_cores, core_group_1, core_group_2, units_per_core_group_1, units_per_core_group_2] = split_work_to_cores (grid, units_to_divide); // CBã®äœæ(2tileåã®åºåãã§ããããã«ç¢ºä¿ãã) constexpr uint32_t dst_cb_id = CBIndex::c_0; CircularBufferConfig cb_output_config = CircularBufferConfig (in_out_num_tiles * dtype_tile_size, {{dst_cb_id, out_data_format}}) . set_page_size (dst_cb_id, dtype_tile_size); tt_metal:: CreateCircularBuffer (program, all_cores, cb_output_config); // Writer kernelã®èšå® const std :: string kernels_dir_path = "ttnn/cpp/ttnn/operations/randn/device/kernels/" ; std :: vector < uint32_t > writer_compile_time_args{dst_cb_id}; tt::tt_metal:: TensorAccessorArgs (output. buffer ()). append_to (writer_compile_time_args); const std :: string writer_file_path = kernels_dir_path + "writer_standard_normal.cpp" ; KernelHandle writer_kernel_id = tt_metal:: CreateKernel ( program, writer_file_path, all_cores, WriterDataMovementConfig (writer_compile_time_args)); // Compute kernelã®èšå® const std :: vector < uint32_t > compute_compile_time_args{dst_cb_id}; const std :: string compute_file_path = kernels_dir_path + "compute_standard_normal.cpp" ; auto [math_fidelity, math_approx_mode, fp32_dest_acc_en, packer_l1_acc, dst_full_sync_en] = get_compute_kernel_config_args (device-> arch (), operation_attributes.compute_kernel_config); KernelHandle compute_kernel_id = CreateKernel ( program, compute_file_path, all_cores, ComputeConfig{ .math_fidelity = math_fidelity, // èšç®ã®ç²ŸåºŠ ref: https://speakerdeck.com/tenstorrent_japan/tensix-core-akitekutiyajie-shuo?slide=26 .fp32_dest_acc_en = true , .dst_full_sync_en = dst_full_sync_en, .math_approx_mode = math_approx_mode, .compile_args = compute_compile_time_args, .defines = compute_defines, }); // foreach in split_work_to_coresã«ããå²ãæ¯ã // kernelåŒæ°(1ã³ã¢ãããã®ä¹±æ°çæã®tileæ°ãåºåã®ã¢ãã¬ã¹)ã®èšå® std :: vector < uint32_t > compute_runtime_args = {seed, tile_offset, units_per_core}; SetRuntimeArgs (program, compute_kernel_id, core, compute_runtime_args); std :: vector < uint32_t > writer_runtime_args = {output. buffer ()-> address (), tile_offset, units_per_core}; SetRuntimeArgs (program, writer_kernel_id, core, writer_runtime_args); // end ããããã¯kernelã®å®è£
ã説æããŸããkernelå
ã§å©çšå¯èœãªAPIã¯ä»¥äžã«ãªããŸãã https://docs.tenstorrent.com/tt-metal/latest/tt-metalium/tt_metal/apis/kernel_apis.html Compute kernel ttnn/cpp/ttnn/operations/randn/device/kernels/compute_standard_normal.cpp ã®æç²ãèšè¿°ããŸãã tileããŒã¹ã®åœä»€ãçšããŠåŠçããŸãã ããã§å®éã«Box-Mulleræ³ã§æšæºæ£èŠä¹±æ°ãçæãããŸãã // Box-Mulleræ³ã§æšæºæ£èŠä¹±æ° (Z1, Z2) ãçæ // Z1 = sqrt(ln(U1) * -2) * cos(U2 * 2pi) // Z2 = sqrt(ln(U1) * -2) * sin(U2 * 2pi) // åºåCBã®æ«å°Ÿã«2tileç¢ºä¿ cb_reserve_back (dst_cb_id, 2 ); // ã¿ã€ã«ã¬ãžã¹ã¿ãç¢ºä¿ tile_regs_acquire (); // U1ã U2ã®äžæ§ä¹±æ°(0, 1)ãã¬ãžã¹ã¿0, 1ã«çæ rand_tile ( 0 , flt_min, one_minus); rand_tile ( 1 , flt_min, one_minus); // sqrt(ln(U1) * -2)ãèšç®ããã¬ãžã¹ã¿0ã«æ ŒçŽ log_tile ( 0 ); mul_unary_tile ( 0 , neg_two); sqrt_tile ( 0 ); // ã¬ãžã¹ã¿2ã«2piãè©°ãã fill_tile_bitcast ( 2 , two_pi); // U2 * 2piãèšç®ããã¬ãžã¹ã¿3, 1ã«æ ŒçŽ mul_binary_tile ( 1 , 2 , 3 ); mul_binary_tile ( 1 , 2 , 1 ); // cos(U2 * 2pi)ãèšç®ããã¬ãžã¹ã¿3ã«æ ŒçŽ cos_tile ( 3 ); // sin(U2 * 2pi)ãèšç®ããã¬ãžã¹ã¿1ã«æ ŒçŽ sin_tile ( 1 ); // Z1 = sqrt(ln(U1) * -2) * cos(U2 * 2pi)ãèšç®ããã¬ãžã¹ã¿3ã«æ ŒçŽ mul_binary_tile ( 0 , 3 , 3 ); // Z2 = sqrt(ln(U1) * -2) * sin(U2 * 2pi)ãèšç®ããã¬ãžã¹ã¿1ã«æ ŒçŽ mul_binary_tile ( 0 , 1 , 1 ); // åºådtypeã BFLOAT16 ã®å Žåã¯å倿 #ifdef OUTPUT_DTYPE_BFLOAT16 typecast_tile< 0 , 5 >( 3 ); typecast_tile< 0 , 5 >( 1 ); #endif // ã¬ãžã¹ã¿èšç®ã®ç¢ºå®ãå®äºåŸ
ã¡ tile_regs_commit (); tile_regs_wait (); // ã¬ãžã¹ã¿3, 1ã®Z1ã Z2ãCBãžæžã蟌㿠pack_tile ( 3 , dst_cb_id); pack_tile ( 1 , dst_cb_id); // ã¬ãžã¹ã¿è§£æŸ tile_regs_release (); // CBã®æ«å°Ÿã«2ã¿ã€ã«è¿œå ããããšãéç¥ cb_push_back (dst_cb_id, 2 ); 次ã«Writer kernel ttnn/cpp/ttnn/operations/randn/device/kernels/writer_standard_normal.cpp ãæç²ããŸãã åºæ¬çã«ã¯Compute kernelããããŒã¿ãåãåãããã®ãŸãŸNOCçµç±ã§æžã蟌ã¿ãŸãã // CBã®å
é ã«2tileãCompute kernelããpushããããŸã§åŸ
〠cb_wait_front (dst_cb_id, 2 ); // CBã®èªã¿åããã€ã³ã¿ååŸ uint32_t dst_cb_read_base = get_read_ptr (dst_cb_id); uint32_t dst_cb_read0_ptr = dst_cb_read_base; uint32_t dst_cb_read1_ptr = dst_cb_read_base + dst_tile_bytes; // NOCã§ã¿ã€ã«åäœã«éåææžã蟌㿠noc_async_write_tile (i, output_addrg, dst_cb_read0_ptr); noc_async_write_tile (i + 1 , output_addrg, dst_cb_read1_ptr); // æžã蟌ã¿å®äºãŸã§ããªã¢ noc_async_write_barrier (); // CBãã2tile pop cb_pop_front (dst_cb_id, 2 ); æåŸã«C++ãPythonããåŒã³åºãããã®å®è£
ã远å ããŸãã ttnn/cpp/ttnn/operations/randn/device/[randn|randn_pybind].[cpp|hpp] Tensor Randn:: invoke ( const ttnn::Shape& shape, MeshDevice& device, const DataType dtype, const Layout layout, const MemoryConfig& memory_config, const std :: optional <DeviceComputeKernelConfig>& compute_kernel_config, uint32_t seed) { auto tensor = ttnn::prim:: randn (shape, dtype, layout, memory_config, device, compute_kernel_config, seed); if (layout != Layout::TILE) { tensor = ttnn:: to_layout (tensor, layout); } return tensor; } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ void bind_randn_operation (py:: module & pymodule) { bind_registered_operation ( pymodule, ttnn::randn, doc, ttnn::pybind_overload_t{ []( const OperationType& self, const ttnn::Shape& shape, MeshDevice& device, const DataType dtype, const Layout layout, const MemoryConfig& memory_config, const std :: optional <DeviceComputeKernelConfig>& compute_kernel_config, uint32_t seed) { return self (shape, device, dtype, layout, memory_config, compute_kernel_config, seed); }, py:: arg ( "shape" ), py:: arg ( "device" ), py:: kw_only (), py:: arg ( "dtype" ) = DataType::BFLOAT16, py:: arg ( "layout" ) = Layout::TILE, py:: arg ( "memory_config" ) = ttnn::DRAM_MEMORY_CONFIG, py:: arg ( "compute_kernel_config" ) = std :: nullopt , py:: arg ( "seed" ) = 0 }); } ä»åå®è£
ãããã詳ããå
šäœã³ãŒãã¯ã以äžã®Pull Requestãåç
§ãã ããã https://github.com/tenstorrent/tt-metal/pull/34508 æ§èœè©äŸ¡ 次ã®ã¹ã¯ãªããã§å®è£
ããttnn.randnãšåŸæ¥ã®opãçµã¿åãããttnn.rand + Box-Muller倿ã®å®è£
ãšæ¯èŒããŸãã è£è¶³ãšããŠCPUã«ããå®è£
ãèšæž¬ããŸãã import math, time, ttnn, torch, numpy as np def rand_box_muller (shape, *, device, dtype, layout, mem, seed): half = (*shape[:- 1 ], shape[- 1 ] // 2 ) u1 = ttnn.rand(half, device=device, dtype=dtype, layout=layout, memory_config=mem, seed=seed + 1234 ) u2 = ttnn.rand(half, device=device, dtype=dtype, layout=layout, memory_config=mem, seed=seed + 4321 ) r = ttnn.sqrt(ttnn.multiply(ttnn.log(u1), - 2.0 )) th = ttnn.multiply(u2, 2.0 * math.pi) z0 = ttnn.multiply(r, ttnn.cos(th)) z1 = ttnn.multiply(r, ttnn.sin(th)) return ttnn.concat([z0, z1], dim=- 1 ) def fused (shape, *, device, dtype, layout, mem, seed): return ttnn.randn(shape, device=device, dtype=dtype, layout=layout, memory_config=mem, seed=seed + 1234 ) def torch_randn (shape, *, dtype, seed): torch.manual_seed(seed+ 1234 ) return torch.randn(shape, dtype=dtype) def bench (name, fn, *, iters, warmup): for i in range (warmup): fn(i) t0 = time.perf_counter_ns() for i in range (iters): fn(i) mean_ms = (time.perf_counter_ns() - t0) / 1e6 / iters print (f "{name}: {mean_ms:.6f} ms/iter" ) return mean_ms DEVICE_ID = 0 SHAPE = ( 1 , 1 , 1024 , 1024 ) ITERS, WARMUP = 10000 , 1000 LAYOUT, MEM, DTYPE = ttnn.TILE_LAYOUT, ttnn.DRAM_MEMORY_CONFIG, ttnn.float32 device = ttnn.open_device(device_id=DEVICE_ID) res_rand_box = bench( "ttnn.rand + Box-Muller" , lambda i: rand_box_muller(SHAPE, device=device, dtype=DTYPE, layout=LAYOUT, mem=MEM, seed=i), iters=ITERS, warmup=WARMUP) res_randn = bench( "ttnn.randn" , lambda i: fused(SHAPE, device=device, dtype=DTYPE, layout=LAYOUT, mem=MEM, seed=i), iters=ITERS, warmup=WARMUP) print (f "Speedup: {res_rand_box / res_randn:.3f}x" ) ttnn.close_device(device) print ( " \n appendix" ) res_torch = bench( "torch.randn" , lambda i: torch_randn(SHAPE, dtype=torch.float32, seed=i), iters=ITERS, warmup=WARMUP) 4ã€ã® Tenstorrent Wormhole⢠n300s ã«ãŒããæèŒããTT-LoudBoxãµãŒãã§å®è¡ããçµæãæ¬¡ã®ããã«ãªããŸãã åŸæ¥ã®opçµã¿åãã(randÃ2 + log/sqrt/sin/cos/mul + concat)ã®å®è£
ã«æ¯ã¹ãŠãä»åfused kernelãå®è£
ããŠçŽ4åã®é«éåãéæããŸããã ã¡ãªã¿ã«ãCPU(Intel® Xeon® Silver 4309Y)ã® torch.randn ã§å®è¡ãããã®ãšæ¯ã¹ããšã¢ã¯ã»ã©ã¬ãŒã¿ã«ãã䞊åå®è¡ã®æ©æµãæããããšãã§ãããšæããŸãã ttnn.rand + Box-Muller: 0.344376 ms/iter ttnn.randn: 0.085173 ms/iter Speedup: 4.043x appendix torch.randn: 4.509201 ms/iter ãŸããåºåããããµã³ãã«ã®ååžãå¯èŠåããŠãæšæºæ£èŠååžãšããŠåé¡ãªãããšã次ã®ããã«ç¢ºèªã§ããŸããã import ttnn, matplotlib.pyplot as plt, numpy as np device = ttnn.open_device(device_id= 0 ) x = ttnn.randn( ( 1 , 1 , 1024 , 1024 ), device=device, dtype=ttnn.float32, layout=ttnn.TILE_LAYOUT, memory_config=ttnn.DRAM_MEMORY_CONFIG, seed= 1234 , ) x = ttnn.to_layout(x, ttnn.ROW_MAJOR_LAYOUT) x = ttnn.from_device(x) x = ttnn.to_torch(x).cpu().numpy().ravel() mean = np.mean(x) var = np.var(x) plt.figure(figsize=( 6 , 4 )) plt.hist(x, bins= 100 , density= True , alpha= 0.7 ) plt.axvline(mean, linewidth= 2 , label=f "mean = {mean:.6f}" ) plt.axvspan(mean - np.sqrt(var), mean + np.sqrt(var), alpha= 0.2 , label=f "var = {var:.6f}" ) plt.title( "Histogram of ttnn.randn()" ) plt.xlabel( "Value" ) plt.ylabel( "Probability Density" ) plt.grid( True ) plt.legend() plt.tight_layout() plt.savefig( "fig.png" ) ttnn.close_device(device) ãŸãšã æ¬èšäºã§ã¯ãTenstorrentã®AIã¢ã¯ã»ã©ã¬ãŒã¿ã¢ãŒããã¯ãã£ãšãã®ç¹åŸŽã玹ä»ããŸããããŸããfused kernelã«ããå
·äœçãªæé©åã®å®è£
æ¹æ³ãšåŸæ¥ææ³ãšæ¯èŒããŠçŽ4åã®é«éåãéæããæ§èœè©äŸ¡çµæãå
±æããŸããã ææ¥ã®ã¢ããã³ãã«ã¬ã³ããŒããæ¥œãã¿ã«ã Dao, Tri. "Flashattention-2: Faster attention with better parallelism and work partitioning." arXiv preprint arXiv:2307.08691 (2023). ↩ Shah, Jay, et al. "Flashattention-3: Fast and accurate attention with asynchrony and low-precision." Advances in Neural Information Processing Systems 37 (2024): 68658-68685. ↩ Box, George E. P. and Mervin E. Muller. âA Note on the Generation of Random Normal Deviates.â Annals of Mathematical Statistics 29 (1958): 610-611. ↩ https://github.com/tenstorrent/tt-metal/blob/main/METALIUM_GUIDE.md#spmd-in-metalium ↩