1 // =============================================================================
2 // === SuiteSparse_GPURuntime/Source/SuiteSparseGPU_Workspace.cpp ==============
3 // =============================================================================
4 
5 // The SuiteSparse_GPURuntime Workspace provides a convenient way to allocate
6 // and free memory on the CPU and/or GPU, and to transfer data between the
7 // CPU and GPU.
8 
9 #include "SuiteSparseGPU_Runtime.hpp"
10 
11 // -----------------------------------------------------------------------------
12 // Workspace constructor
13 // -----------------------------------------------------------------------------
14 
Workspace(size_t _nitems,size_t _size_of_item)15 Workspace::Workspace
16 (
17     size_t _nitems,                 // number of items to allocate
18     size_t _size_of_item            // size of each item
19 )
20 {
21     nitems = _nitems;
22     size_of_item = _size_of_item;
23 
24     totalSize = nitems * size_of_item;
25 
26     // check for integer overflow
27     if (totalSize != ((double) nitems) * size_of_item)
28     {
29         totalSize = 0 ;            // size_t overflow
30     }
31 
32     // lazyAllocate = false;       // always false, left for future use
33 
34     cpuReference = NULL;            // no CPU memory allocated yet
35     gpuReference = NULL;            // no GPU memory allocated yet
36 }
37 
38 // -----------------------------------------------------------------------------
39 // Workspace destructor
40 // -----------------------------------------------------------------------------
41 
~Workspace()42 Workspace::~Workspace()
43 {
44 }
45 
46 // -----------------------------------------------------------------------------
47 // allocate workspace
48 // -----------------------------------------------------------------------------
49 
allocate(size_t nitems,size_t size_of_item,bool doCalloc,bool cpuAlloc,bool gpuAlloc,bool pageLocked)50 Workspace *Workspace::allocate
51 (
52     size_t nitems,          // number of items
53     size_t size_of_item,    // size of each item
54     bool doCalloc,          // true if calloc instead of malloc
55     bool cpuAlloc,          // true if allocating on the CPU
56     bool gpuAlloc,          // true if allocating on the GPU
57     bool pageLocked         // true if pagelocked on the CPU
58 )
59 {
60     // Cannot use calloc directly since that's a member function,
61     // and this is a static member function.
62     Workspace *returner = (Workspace*)
63         Workspace::cpu_calloc (1, sizeof(Workspace), false) ;
64 
65     if (returner)
66     {
67         new (returner) Workspace (nitems, size_of_item) ;
68 
69         /* Set whether the user wants the address page-locked. */
70         returner->pageLocked = pageLocked ;
71 
72         /* Do the allocation & handle any errors. */
73         bool okay = (doCalloc ? returner->ws_calloc (cpuAlloc, gpuAlloc)  :
74                                 returner->ws_malloc (cpuAlloc, gpuAlloc)) ;
75         if (!okay)
76         {
77             returner = Workspace::destroy (returner) ;
78         }
79     }
80 
81     return (returner) ;
82 }
83 
84 // -----------------------------------------------------------------------------
85 // destroy workspace, freeing memory
86 // -----------------------------------------------------------------------------
87 
destroy(Workspace * address)88 Workspace *Workspace::destroy
89 (
90     Workspace *address
91 )
92 {
93     if(address)
94     {
95         address->ws_free(address->cpu(), address->gpu());
96         SuiteSparse_free(address);
97     }
98     return NULL;
99 }
100 
101 // -----------------------------------------------------------------------------
102 // ws_malloc: malloc workspace on CPU and/or GPU
103 // -----------------------------------------------------------------------------
104 
ws_malloc(bool cpuAlloc,bool gpuAlloc)105 bool Workspace::ws_malloc(bool cpuAlloc, bool gpuAlloc)
106 {
107     if(cpuAlloc)
108     {
109         cpuReference = Workspace::cpu_malloc(nitems, size_of_item, pageLocked);
110     }
111     if(gpuAlloc)
112     {
113         gpuReference = Workspace::gpu_malloc(nitems, size_of_item);
114     }
115 
116     bool cpuSideOk = IMPLIES(cpuAlloc, cpuReference != NULL);
117     bool gpuSideOk = IMPLIES(gpuAlloc, gpuReference != NULL)
118         // || lazyAllocate
119         ;
120     return (cpuSideOk && gpuSideOk);
121 }
122 
123 // -----------------------------------------------------------------------------
124 // ws_calloc: calloc workspace on CPU and/or GPU
125 // -----------------------------------------------------------------------------
126 
ws_calloc(bool cpuAlloc,bool gpuAlloc)127 bool Workspace::ws_calloc(bool cpuAlloc, bool gpuAlloc)
128 {
129     if(cpuAlloc)
130     {
131         cpuReference = Workspace::cpu_calloc(nitems, size_of_item, pageLocked);
132     }
133     if(gpuAlloc)
134     {
135         gpuReference = Workspace::gpu_calloc(nitems, size_of_item);
136     }
137 
138     bool cpuSideOk = IMPLIES(cpuAlloc, cpuReference != NULL);
139     bool gpuSideOk = IMPLIES(gpuAlloc, gpuReference != NULL)
140         // || lazyAllocate
141         ;
142     return (cpuSideOk && gpuSideOk);
143 }
144 
145 // -----------------------------------------------------------------------------
146 // ws_free: free workspace on CPU and/or GPU
147 // -----------------------------------------------------------------------------
148 
ws_free(bool cpuFree,bool gpuFree)149 void Workspace::ws_free(bool cpuFree, bool gpuFree)
150 {
151     if(cpuFree) Workspace::cpu_free(cpuReference, pageLocked);
152     if(gpuFree) Workspace::gpu_free(gpuReference);
153 }
154