source: icGREP/icgrep-devel/icgrep/kernels/mmap_kernel.cpp @ 5418

Last change on this file since 5418 was 5418, checked in by nmedfort, 2 years ago

Removed non-functional CUDA code from icgrep and consolidated grep and multigrep mode into a single function; allowed segment parallel pipeline to utilize process as its initial thread; modified MMapSourceKernel to map and perform mmap directly and advise the OS to drop consumed data streams.

File size: 4.8 KB
Line 
1/*
2 *  Copyright (c) 2017 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 */
5#include "mmap_kernel.h"
6#include <llvm/IR/Module.h>
7#include <IR_Gen/idisa_builder.h>
8#include <kernels/streamset.h>
9
10using namespace llvm;
11
12namespace kernel {
13
14void MMapSourceKernel::generateInitializeMethod() {
15    Value * fd = getScalarField("fileDescriptor");
16    Value * fileSize = iBuilder->CreateFileSize(fd);
17    if (mCodeUnitWidth > 8) {
18        fileSize = iBuilder->CreateUDiv(fileSize, iBuilder->getSize(mCodeUnitWidth / 8));
19    }
20    Value * buffer = iBuilder->CreateFileSourceMMap(fd, fileSize);
21    setBaseAddress("sourceBuffer", buffer);
22    setBufferedSize("sourceBuffer", fileSize);   
23    setScalarField("readableBuffer", buffer);
24    setScalarField("fileSize", fileSize);
25    iBuilder->CreateMAdvise(buffer, fileSize, CBuilder::MMAP_WILLNEED);
26}
27
28void MMapSourceKernel::generateDoSegmentMethod() {
29
30    BasicBlock * dropPages = CreateBasicBlock("dropPages");
31    BasicBlock * produceData = CreateBasicBlock("produceData");
32    BasicBlock * setTermination = CreateBasicBlock("setTermination");
33    BasicBlock * mmapSourceExit = CreateBasicBlock("mmapSourceExit");
34
35    // instruct the OS that it can safely drop any fully consumed pages
36    Value * consumed = getConsumedItemCount("sourceBuffer");
37    Type * const consumedTy = consumed->getType();
38    Type * const voidPtrTy = iBuilder->getVoidPtrTy();
39
40    // multiply the consumed count by the code unit size then mask off any partial pages
41    if (mCodeUnitWidth > 8) {
42        consumed = iBuilder->CreateMul(consumed, iBuilder->getSize(mCodeUnitWidth / 8));
43    }
44    const auto pageSize = getpagesize();
45    if (LLVM_LIKELY((pageSize & (pageSize - 1)) == 0)) {
46        consumed = iBuilder->CreateAnd(consumed, ConstantExpr::getNot(ConstantInt::get(consumedTy, pageSize - 1)));
47    } else {
48        consumed = iBuilder->CreateSub(consumed, iBuilder->CreateURem(consumed, ConstantInt::get(consumedTy, pageSize)));
49    }
50    Value * sourceBuffer = getBaseAddress("sourceBuffer");
51    sourceBuffer = iBuilder->CreatePtrToInt(sourceBuffer, consumedTy);
52    Value * consumedBuffer = iBuilder->CreateAdd(sourceBuffer, consumed);
53    Value * readableBuffer = getScalarField("readableBuffer");
54    readableBuffer = iBuilder->CreatePtrToInt(readableBuffer, consumedTy);
55    Value * unnecessaryBytes = iBuilder->CreateSub(consumedBuffer, readableBuffer);
56    // avoid calling madvise unless an actual page table change could occur
57    Value * hasPagesToDrop = iBuilder->CreateICmpEQ(unnecessaryBytes, ConstantInt::getNullValue(unnecessaryBytes->getType()));
58    iBuilder->CreateLikelyCondBr(hasPagesToDrop, produceData, dropPages);
59
60    iBuilder->SetInsertPoint(dropPages);
61    iBuilder->CreateMAdvise(iBuilder->CreateIntToPtr(readableBuffer, voidPtrTy), unnecessaryBytes, CBuilder::MMAP_DONTNEED);   
62    readableBuffer = iBuilder->CreateIntToPtr(iBuilder->CreateAdd(readableBuffer, unnecessaryBytes), voidPtrTy);
63    setScalarField("readableBuffer", readableBuffer);
64    iBuilder->CreateBr(produceData);
65
66    // determine whether or not we've exhausted the file buffer
67    iBuilder->SetInsertPoint(produceData);
68    ConstantInt * segmentItems = iBuilder->getSize(mSegmentBlocks * iBuilder->getBitBlockWidth());
69    Value * const fileSize = getBufferedSize("sourceBuffer");
70    Value * produced = getProducedItemCount("sourceBuffer");
71    produced = iBuilder->CreateAdd(produced, segmentItems);
72
73    Value * lessThanFullSegment = iBuilder->CreateICmpULT(fileSize, produced);
74    iBuilder->CreateCondBr(lessThanFullSegment, setTermination, mmapSourceExit);
75    iBuilder->SetInsertPoint(setTermination);
76
77    setTerminationSignal();
78    iBuilder->CreateBr(mmapSourceExit);
79
80    // finally, set the "produced" count to reflect current position in the file
81    iBuilder->SetInsertPoint(mmapSourceExit);
82    PHINode * itemsRead = iBuilder->CreatePHI(produced->getType(), 2);
83    itemsRead->addIncoming(produced, produceData);
84    itemsRead->addIncoming(fileSize, setTermination);
85    setProducedItemCount("sourceBuffer", itemsRead);
86}
87
88void MMapSourceKernel::generateFinalizeMethod() {
89    Value * buffer = getBaseAddress("sourceBuffer");
90    Value * fileSize = getBufferedSize("sourceBuffer");
91    iBuilder->CreateMUnmap(buffer, fileSize);
92}
93
94MMapSourceKernel::MMapSourceKernel(IDISA::IDISA_Builder * iBuilder, unsigned blocksPerSegment, unsigned codeUnitWidth)
95    : SegmentOrientedKernel(iBuilder, "Parabix:mmap_source" + std::to_string(blocksPerSegment) + "@" + std::to_string(codeUnitWidth),
96    {},
97    {Binding{iBuilder->getStreamSetTy(1, codeUnitWidth), "sourceBuffer"}},
98    {Binding{iBuilder->getInt32Ty(), "fileDescriptor"}}, {Binding{iBuilder->getSizeTy(), "fileSize"}}, {Binding{iBuilder->getVoidPtrTy(), "readableBuffer"}})
99, mSegmentBlocks(blocksPerSegment)
100, mCodeUnitWidth(codeUnitWidth) {
101
102}
103
104}
Note: See TracBrowser for help on using the repository browser.