| 528 | |
| 529 | template <class T, EPtrType Type> |
| 530 | inline TCudaBuffer<T, TStripeMapping, Type> ParallelStripeView(const TCudaBuffer<T, TStripeMapping, Type>& buffer, |
| 531 | const TSlice& slice, |
| 532 | ui32 column = 0) { |
| 533 | const TStripeMapping& srcMapping = buffer.GetMapping(); |
| 534 | TCudaBuffer<T, TStripeMapping, Type> parallelViewBuffer; |
| 535 | const ui32 devCount = NCudaLib::GetCudaManager().GetDeviceCount(); |
| 536 | |
| 537 | TVector<TSlice> srcSlices(devCount); |
| 538 | TVector<TSlice> viewSlices(devCount); |
| 539 | |
| 540 | { |
| 541 | TSlice firstDevSlice = srcMapping.DeviceSlice(0); |
| 542 | CB_ENSURE(slice.Size() <= firstDevSlice.Size(), slice << " / " << firstDevSlice); |
| 543 | |
| 544 | ui32 cursor = 0; |
| 545 | for (ui32 dev = 0; dev < devCount; ++dev) { |
| 546 | srcSlices[dev] = TSlice(slice.Left + firstDevSlice.Size() * dev, slice.Right + firstDevSlice.Size() * dev); |
| 547 | viewSlices[dev] = TSlice(cursor, cursor + slice.Size()); |
| 548 | cursor += slice.Size(); |
| 549 | CB_ENSURE(srcMapping.DeviceSlice(dev).Size() == firstDevSlice.Size()); |
| 550 | } |
| 551 | |
| 552 | parallelViewBuffer.Mapping = NCudaLib::TStripeMapping(std::move(viewSlices), |
| 553 | srcMapping.SingleObjectSize()); |
| 554 | } |
| 555 | |
| 556 | for (ui32 dev : parallelViewBuffer.Mapping.NonEmptyDevices()) { |
| 557 | const ui64 columnsShift = NAligment::ColumnShift(srcMapping.MemoryUsageAt(dev), column); |
| 558 | |
| 559 | const auto devSlice = srcSlices[dev]; |
| 560 | if (buffer.Buffers[dev].NotEmpty()) { |
| 561 | parallelViewBuffer.Buffers[dev] = buffer.Buffers[dev].ShiftedBuffer(columnsShift + srcMapping.DeviceMemoryOffset(dev, devSlice)); |
| 562 | } |
| 563 | } |
| 564 | parallelViewBuffer.IsSliceView = true; |
| 565 | |
| 566 | return parallelViewBuffer; |
| 567 | } |
| 568 | |
| 569 | template <class T> |
| 570 | class TParallelStripeVectorBuilder { |
no test coverage detected