• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

bernardladenthin / BitcoinAddressFinder / #308

28 Apr 2025 10:01PM UTC coverage: 68.174% (-0.7%) from 68.832%
#308

push

bernardladenthin
Refactor OpenCL handling for device endianness and dynamic platform selection

22 of 76 new or added lines in 10 files covered. (28.95%)

1 existing line in 1 file now uncovered.

1221 of 1791 relevant lines covered (68.17%)

0.68 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

8.62
/src/main/java/net/ladenthin/bitcoinaddressfinder/opencl/OpenCLBuilder.java
1
// @formatter:off
2
/**
3
 * Copyright 2022 Bernard Ladenthin bernard.ladenthin@gmail.com
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at
8
 *
9
 *    http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 *
17
 */
18
// @formatter:on
19
package net.ladenthin.bitcoinaddressfinder.opencl;
20

21
import java.lang.reflect.Field;
22
import java.nio.ByteBuffer;
23
import java.nio.ByteOrder;
24
import java.util.ArrayList;
25
import java.util.List;
26
import net.ladenthin.bitcoinaddressfinder.ByteBufferUtility;
27
import org.apache.maven.artifact.versioning.ComparableVersion;
28
import static org.jocl.CL.CL_CONTEXT_PLATFORM;
29
import static org.jocl.CL.CL_DEVICE_ADDRESS_BITS;
30
import static org.jocl.CL.CL_DEVICE_ENDIAN_LITTLE;
31
import static org.jocl.CL.CL_DEVICE_ERROR_CORRECTION_SUPPORT;
32
import static org.jocl.CL.CL_DEVICE_EXTENSIONS;
33
import static org.jocl.CL.CL_DEVICE_GLOBAL_MEM_SIZE;
34
import static org.jocl.CL.CL_DEVICE_IMAGE2D_MAX_HEIGHT;
35
import static org.jocl.CL.CL_DEVICE_IMAGE2D_MAX_WIDTH;
36
import static org.jocl.CL.CL_DEVICE_IMAGE3D_MAX_DEPTH;
37
import static org.jocl.CL.CL_DEVICE_IMAGE3D_MAX_HEIGHT;
38
import static org.jocl.CL.CL_DEVICE_IMAGE3D_MAX_WIDTH;
39
import static org.jocl.CL.CL_DEVICE_IMAGE_SUPPORT;
40
import static org.jocl.CL.CL_DEVICE_LOCAL_MEM_SIZE;
41
import static org.jocl.CL.CL_DEVICE_LOCAL_MEM_TYPE;
42
import static org.jocl.CL.CL_DEVICE_MAX_CLOCK_FREQUENCY;
43
import static org.jocl.CL.CL_DEVICE_MAX_COMPUTE_UNITS;
44
import static org.jocl.CL.CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE;
45
import static org.jocl.CL.CL_DEVICE_MAX_MEM_ALLOC_SIZE;
46
import static org.jocl.CL.CL_DEVICE_MAX_READ_IMAGE_ARGS;
47
import static org.jocl.CL.CL_DEVICE_MAX_WORK_GROUP_SIZE;
48
import static org.jocl.CL.CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS;
49
import static org.jocl.CL.CL_DEVICE_MAX_WORK_ITEM_SIZES;
50
import static org.jocl.CL.CL_DEVICE_MAX_WRITE_IMAGE_ARGS;
51
import static org.jocl.CL.CL_DEVICE_NAME;
52
import static org.jocl.CL.CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR;
53
import static org.jocl.CL.CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE;
54
import static org.jocl.CL.CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT;
55
import static org.jocl.CL.CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT;
56
import static org.jocl.CL.CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG;
57
import static org.jocl.CL.CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT;
58
import static org.jocl.CL.CL_DEVICE_PROFILE;
59
import static org.jocl.CL.CL_DEVICE_QUEUE_PROPERTIES;
60
import static org.jocl.CL.CL_DEVICE_SINGLE_FP_CONFIG;
61
import static org.jocl.CL.CL_DEVICE_TYPE;
62
import static org.jocl.CL.CL_DEVICE_TYPE_ALL;
63
import static org.jocl.CL.CL_DEVICE_VENDOR;
64
import static org.jocl.CL.CL_DEVICE_VERSION;
65
import static org.jocl.CL.CL_DRIVER_VERSION;
66
import static org.jocl.CL.CL_PLATFORM_NAME;
67
import static org.jocl.CL.clGetDeviceIDs;
68
import static org.jocl.CL.clGetDeviceInfo;
69
import static org.jocl.CL.clGetPlatformIDs;
70
import static org.jocl.CL.clGetPlatformInfo;
71
import org.jocl.Pointer;
72
import org.jocl.Sizeof;
73
import org.jocl.cl_context_properties;
74
import org.jocl.cl_device_id;
75
import org.jocl.cl_platform_id;
76

77
public class OpenCLBuilder {
1✔
78
    
79
    public static boolean TRANSFORM_TO_PRINT = true;
1✔
80
    
81
    public List<OpenCLPlatform> build() {
82
        // Obtain the number of platforms
83
        int numPlatforms[] = new int[1];
×
84
        clGetPlatformIDs(0, null, numPlatforms);
×
85

86
        // Obtain the platform IDs
87
        List<OpenCLPlatform> openCLPlatforms = new ArrayList<>();
×
88
        cl_platform_id platforms[] = new cl_platform_id[numPlatforms[0]];
×
89
        clGetPlatformIDs(platforms.length, platforms, null);
×
90

91
        for (int i=0; i<platforms.length; i++) {
×
92
            // Collect all devices of all platforms
93
            final cl_platform_id platformId = platforms[i];
×
94
            
95
            // Initialize the context properties
NEW
96
            cl_context_properties contextProperties = new cl_context_properties();
×
NEW
97
            contextProperties.addProperty(CL_CONTEXT_PLATFORM, platformId);
×
98

99
            String platformName = getString(platformId, CL_PLATFORM_NAME);
×
100
            
101
            // Obtain the number of devices for the current platform
NEW
102
            int numDevicesArray[] = new int[1];
×
NEW
103
            clGetDeviceIDs(platformId, CL_DEVICE_TYPE_ALL, 0, null, numDevicesArray);
×
NEW
104
            int numDevices = numDevicesArray[0];
×
105
            
NEW
106
            cl_device_id devicesArray[] = new cl_device_id[numDevices];
×
NEW
107
            clGetDeviceIDs(platformId, CL_DEVICE_TYPE_ALL, numDevices, devicesArray, null);
×
108

109
            List<OpenCLDevice> openCLDevices = new ArrayList<>();
×
110
            for (cl_device_id device : devicesArray) {
×
111
                OpenCLDevice openCLDevice = createOpenCLDevice(device);
×
112
                openCLDevices.add(openCLDevice);
×
113
            }
114
            
NEW
115
            OpenCLPlatform openCLPlatform = new OpenCLPlatform(platformName, contextProperties, openCLDevices);
×
116
            openCLPlatforms.add(openCLPlatform);
×
117
        }
118
        
119
        return openCLPlatforms;
×
120
    }
121

122
    private OpenCLDevice createOpenCLDevice(cl_device_id device) {
123
        String deviceName = getString(device, CL_DEVICE_NAME);
×
124
        String deviceVendor = getString(device, CL_DEVICE_VENDOR);
×
125
        String driverVersion = getString(device, CL_DRIVER_VERSION);
×
126
        String deviceProfile = getString(device, CL_DEVICE_PROFILE);
×
127
        String deviceVersion = getString(device, CL_DEVICE_VERSION);
×
128
        String deviceExtensions = getString(device, CL_DEVICE_EXTENSIONS);
×
NEW
129
        boolean endianLittle = getInt(device, CL_DEVICE_ENDIAN_LITTLE) == 1;
×
130
        long deviceType = getLong(device, CL_DEVICE_TYPE);
×
131
        int maxComputeUnits = getInt(device, CL_DEVICE_MAX_COMPUTE_UNITS);
×
132
        long maxWorkItemDimensions = getLong(device, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS);
×
133
        long maxWorkItemSizes[] = getSizes(device, CL_DEVICE_MAX_WORK_ITEM_SIZES, 3);
×
134
        long maxWorkGroupSize = getSize(device, CL_DEVICE_MAX_WORK_GROUP_SIZE);
×
135
        long maxClockFrequency = getLong(device, CL_DEVICE_MAX_CLOCK_FREQUENCY);
×
136
        int addressBits = getInt(device, CL_DEVICE_ADDRESS_BITS);
×
137
        long maxMemAllocSize = getLong(device, CL_DEVICE_MAX_MEM_ALLOC_SIZE);
×
138
        long globalMemSize = getLong(device, CL_DEVICE_GLOBAL_MEM_SIZE);
×
139
        int errorCorrectionSupport = getInt(device, CL_DEVICE_ERROR_CORRECTION_SUPPORT);
×
140
        int localMemType = getInt(device, CL_DEVICE_LOCAL_MEM_TYPE);
×
141
        long localMemSize = getLong(device, CL_DEVICE_LOCAL_MEM_SIZE);
×
142
        long maxConstantBufferSize = getLong(device, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE);
×
143
        long queueProperties = getLong(device, CL_DEVICE_QUEUE_PROPERTIES);
×
144
        int imageSupport = getInt(device, CL_DEVICE_IMAGE_SUPPORT);
×
145
        int maxReadImageArgs = getInt(device, CL_DEVICE_MAX_READ_IMAGE_ARGS);
×
146
        int maxWriteImageArgs = getInt(device, CL_DEVICE_MAX_WRITE_IMAGE_ARGS);
×
147
        long singleFpConfig = getLong(device, CL_DEVICE_SINGLE_FP_CONFIG);
×
148
        long image2dMaxWidth = getSize(device, CL_DEVICE_IMAGE2D_MAX_WIDTH);
×
149
        long image2dMaxHeight = getSize(device, CL_DEVICE_IMAGE2D_MAX_HEIGHT);
×
150
        long image3dMaxWidth = getSize(device, CL_DEVICE_IMAGE3D_MAX_WIDTH);
×
151
        long image3dMaxHeight = getSize(device, CL_DEVICE_IMAGE3D_MAX_HEIGHT);
×
152
        long image3dMaxDepth = getSize(device, CL_DEVICE_IMAGE3D_MAX_DEPTH);
×
153
        int preferredVectorWidthChar = getInt(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR);
×
154
        int preferredVectorWidthShort = getInt(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT);
×
155
        int preferredVectorWidthInt = getInt(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT);
×
156
        int preferredVectorWidthLong = getInt(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG);
×
157
        int preferredVectorWidthFloat = getInt(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT);
×
158
        int preferredVectorWidthDouble = getInt(device, CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE);
×
159
        
160
        OpenCLDevice openCLDevice = new OpenCLDevice(
×
161
                device,
162
                deviceName,
163
                deviceVendor,
164
                driverVersion,
165
                deviceProfile,
166
                deviceVersion,
167
                deviceExtensions,
168
                deviceType,
169
                endianLittle,
170
                maxComputeUnits,
171
                maxWorkItemDimensions,
172
                maxWorkItemSizes,
173
                maxWorkGroupSize,
174
                maxClockFrequency,
175
                addressBits,
176
                maxMemAllocSize,
177
                globalMemSize,
178
                errorCorrectionSupport,
179
                localMemType,
180
                localMemSize,
181
                maxConstantBufferSize,
182
                queueProperties,
183
                imageSupport,
184
                maxReadImageArgs,
185
                maxWriteImageArgs,
186
                singleFpConfig,
187
                image2dMaxWidth,
188
                image2dMaxHeight,
189
                image3dMaxWidth,
190
                image3dMaxHeight,
191
                image3dMaxDepth,
192
                preferredVectorWidthChar,
193
                preferredVectorWidthShort,
194
                preferredVectorWidthInt,
195
                preferredVectorWidthLong,
196
                preferredVectorWidthFloat,
197
                preferredVectorWidthDouble
198
        );
199
        
200
        return openCLDevice;
×
201
    }
202
    
203
    
204
    public static boolean isOpenCLnativeLibraryLoadable() {
205
        try {
206
            Class.forName("org.jocl.CL");
×
207
            Field field = org.jocl.CL.class.getDeclaredField("nativeLibraryLoaded");
×
208
            field.setAccessible(true);
×
209
            return field.getBoolean(null);
×
210
        } catch(java.lang.UnsatisfiedLinkError e) {
1✔
211
            return false;
1✔
212
        } catch (java.lang.NoClassDefFoundError e) {
1✔
213
            return false;
1✔
214
        } catch (Exception e) {
×
215
            e.printStackTrace();
×
216
            return false;
×
217
        }
218
    }
219
    
220
    public static boolean isOneOpenCL2_0OrGreaterDeviceAvailable(List<OpenCLPlatform> openCLPlatforms) {
221
        for (OpenCLPlatform openCLPlatform : openCLPlatforms) {
×
222
            List<OpenCLDevice> openCLDevices = openCLPlatform.openCLDevices();
×
223
            for (OpenCLDevice openCLDevice : openCLDevices) {
×
224
                if (isOpenCL2_0OrGreater(openCLDevice.getDeviceVersionAsComparableVersion())) {
×
225
                    return true;
×
226
                }
227
            }
×
228
        }
×
229
        return false;
×
230
    }
231

232
    public static boolean isOpenCL2_0OrGreater(ComparableVersion openCLDeviceVersion) {
233
        final ComparableVersion v2_0 = new ComparableVersion("2.0");
1✔
234
        if (openCLDeviceVersion.compareTo(v2_0) >= 0) {
1✔
235
            return true;
1✔
236
        }
237
        return false;
1✔
238
    }
239
    
240
    /**
241
     * Returns the value of the device info parameter with the given name
242
     *
243
     * @param device The device
244
     * @param paramName The parameter name
245
     * @return The value
246
     */
247
    private static int getInt(cl_device_id device, int paramName)
248
    {
249
        return getInts(device, paramName, 1)[0];
×
250
    }
251

252
    /**
253
     * Returns the values of the device info parameter with the given name
254
     *
255
     * @param device The device
256
     * @param paramName The parameter name
257
     * @param numValues The number of values
258
     * @return The value
259
     */
260
    private static int[] getInts(cl_device_id device, int paramName, int numValues)
261
    {
262
        int values[] = new int[numValues];
×
263
        clGetDeviceInfo(device, paramName, (long)Sizeof.cl_int * numValues, Pointer.to(values), null);
×
264
        return values;
×
265
    }
266

267
    /**
268
     * Returns the value of the device info parameter with the given name
269
     *
270
     * @param device The device
271
     * @param paramName The parameter name
272
     * @return The value
273
     */
274
    private static long getLong(cl_device_id device, int paramName)
275
    {
276
        return getLongs(device, paramName, 1)[0];
×
277
    }
278

279
    /**
280
     * Returns the values of the device info parameter with the given name
281
     *
282
     * @param device The device
283
     * @param paramName The parameter name
284
     * @param numValues The number of values
285
     * @return The value
286
     */
287
    private static long[] getLongs(cl_device_id device, int paramName, int numValues)
288
    {
289
        long values[] = new long[numValues];
×
290
        clGetDeviceInfo(device, paramName, (long)Sizeof.cl_long * numValues, Pointer.to(values), null);
×
291
        return values;
×
292
    }
293

294
    /**
295
     * Returns the value of the device info parameter with the given name
296
     *
297
     * @param device The device
298
     * @param paramName The parameter name
299
     * @return The value
300
     */
301
    private static String getString(cl_device_id device, int paramName)
302
    {
303
        // Obtain the length of the string that will be queried
304
        long size[] = new long[1];
×
305
        clGetDeviceInfo(device, paramName, 0, null, size);
×
306

307
        // Create a buffer of the appropriate size and fill it with the info
308
        byte buffer[] = new byte[(int)size[0]];
×
309
        clGetDeviceInfo(device, paramName, buffer.length, Pointer.to(buffer), null);
×
310

311
        // Create a string from the buffer (excluding the trailing \0 byte)
312
        return new String(buffer, 0, buffer.length-1);
×
313
    }
314

315
    /**
316
     * Returns the value of the platform info parameter with the given name
317
     *
318
     * @param platform The platform
319
     * @param paramName The parameter name
320
     * @return The value
321
     */
322
    private static String getString(cl_platform_id platform, int paramName)
323
    {
324
        // Obtain the length of the string that will be queried
325
        long size[] = new long[1];
×
326
        clGetPlatformInfo(platform, paramName, 0, null, size);
×
327

328
        // Create a buffer of the appropriate size and fill it with the info
329
        byte buffer[] = new byte[(int)size[0]];
×
330
        clGetPlatformInfo(platform, paramName, buffer.length, Pointer.to(buffer), null);
×
331

332
        // Create a string from the buffer (excluding the trailing \0 byte)
333
        return new String(buffer, 0, buffer.length-1);
×
334
    }
335
    
336
    /**
337
     * Returns the value of the device info parameter with the given name
338
     *
339
     * @param device The device
340
     * @param paramName The parameter name
341
     * @return The value
342
     */
343
    private static long getSize(cl_device_id device, int paramName)
344
    {
345
        return getSizes(device, paramName, 1)[0];
×
346
    }
347
    
348
    /**
349
     * Returns the values of the device info parameter with the given name
350
     *
351
     * @param device The device
352
     * @param paramName The parameter name
353
     * @param numValues The number of values
354
     * @return The value
355
     */
356
    static long[] getSizes(cl_device_id device, int paramName, int numValues)
357
    {
358
        // The size of the returned data has to depend on 
359
        // the size of a size_t, which is handled here
360
        long size = (long)numValues * Sizeof.size_t;
×
361
        ByteBuffer buffer = ByteBuffer.allocate(
×
362
            ByteBufferUtility.ensureByteBufferCapacityFitsInt(size)).order(ByteOrder.nativeOrder());
×
363
        clGetDeviceInfo(device, paramName, size, 
×
364
            Pointer.to(buffer), null);
×
365
        long values[] = new long[numValues];
×
366
        if (Sizeof.size_t == 4)
×
367
        {
368
            for (int i=0; i<numValues; i++)
×
369
            {
370
                values[i] = buffer.getInt(i * Sizeof.size_t);
×
371
            }
372
        }
373
        else
374
        {
375
            for (int i=0; i<numValues; i++)
×
376
            {
377
                values[i] = buffer.getLong(i * Sizeof.size_t);
×
378
            }
379
        }
380
        return values;
×
381
    }
382
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc