MSM - supporting all window sizes (#534)

This PR enables using MSM with any value of c.

Note: default c isn't necessarily optimal, the user is expected to
choose c and the precomputation factor that give the best results for
the relevant case.

---------

Co-authored-by: Jeremy Felder <jeremy.felder1@gmail.com>
This commit is contained in:
HadarIngonyama
2024-06-17 15:57:24 +03:00
committed by GitHub
parent af9ec76506
commit 8936d9c800
46 changed files with 688 additions and 282 deletions

View File

@@ -116,13 +116,13 @@ func MsmCheck(scalars HostOrDeviceSlice, points HostOrDeviceSlice, cfg *MSMConfi
return scalars.AsUnsafePointer(), points.AsUnsafePointer(), results.AsUnsafePointer(), size, unsafe.Pointer(cfg)
}
func PrecomputeBasesCheck(points HostOrDeviceSlice, precomputeFactor int32, outputBases DeviceSlice) (unsafe.Pointer, unsafe.Pointer) {
func PrecomputePointsCheck(points HostOrDeviceSlice, cfg *MSMConfig, outputBases DeviceSlice) (unsafe.Pointer, unsafe.Pointer) {
outputBasesLength, pointsLength := outputBases.Len(), points.Len()
if outputBasesLength != pointsLength*int(precomputeFactor) {
if outputBasesLength != pointsLength*int(cfg.PrecomputeFactor) {
errorString := fmt.Sprintf(
"Precompute factor is probably incorrect: expected %d but got %d",
outputBasesLength/pointsLength,
precomputeFactor,
cfg.PrecomputeFactor,
)
panic(errorString)
}
@@ -131,5 +131,8 @@ func PrecomputeBasesCheck(points HostOrDeviceSlice, precomputeFactor int32, outp
points.(DeviceSlice).CheckDevice()
}
cfg.pointsSize = int32(pointsLength)
cfg.arePointsOnDevice = points.IsOnDevice()
return points.AsUnsafePointer(), outputBases.AsUnsafePointer()
}

View File

@@ -16,6 +16,7 @@ typedef struct DeviceContext DeviceContext;
cudaError_t bls12_377_g2_msm_cuda(const scalar_t* scalars,const g2_affine_t* points, int count, MSMConfig* config, g2_projective_t* out);
cudaError_t bls12_377_g2_precompute_msm_bases_cuda(g2_affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, g2_affine_t* out);
cudaError_t bls12_377_g2_precompute_msm_points_cuda(g2_affine_t* points, int msm_size, MSMConfig* config, g2_affine_t* out);
#ifdef __cplusplus
}

View File

@@ -28,8 +28,13 @@ func G2Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *c
return err
}
// Deprecated: G2PrecomputeBases exists for backward compatibility.
// It may cause issues if an MSM with a different `c` value is used with precomputed points and it will be removed in a future version.
// G2PrecomputePoints should be used instead.
func G2PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError {
pointsPointer, outputBasesPointer := core.PrecomputeBasesCheck(points, precomputeFactor, outputBases)
cfg := G2GetDefaultMSMConfig()
cfg.PrecomputeFactor = precomputeFactor
pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases)
cPoints := (*C.g2_affine_t)(pointsPointer)
cPointsLen := (C.int)(points.Len())
@@ -43,3 +48,16 @@ func G2PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c
err := (cr.CudaError)(__ret)
return err
}
func G2PrecomputePoints(points core.HostOrDeviceSlice, msmSize int, cfg *core.MSMConfig, outputBases core.DeviceSlice) cr.CudaError {
pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases)
cPoints := (*C.g2_affine_t)(pointsPointer)
cMsmSize := (C.int)(msmSize)
cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg))
cOutputBases := (*C.g2_affine_t)(outputBasesPointer)
__ret := C.bls12_377_g2_precompute_msm_points_cuda(cPoints, cMsmSize, cCfg, cOutputBases)
err := (cr.CudaError)(__ret)
return err
}

View File

@@ -16,6 +16,7 @@ typedef struct DeviceContext DeviceContext;
cudaError_t bls12_377_msm_cuda(const scalar_t* scalars,const affine_t* points, int count, MSMConfig* config, projective_t* out);
cudaError_t bls12_377_precompute_msm_bases_cuda(affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, affine_t* out);
cudaError_t bls12_377_precompute_msm_points_cuda(affine_t* points, int msm_size, MSMConfig* config, affine_t* out);
#ifdef __cplusplus
}

View File

@@ -28,8 +28,13 @@ func Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *cor
return err
}
// Deprecated: PrecomputeBases exists for backward compatibility.
// It may cause issues if an MSM with a different `c` value is used with precomputed points and it will be removed in a future version.
// PrecomputePoints should be used instead.
func PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError {
pointsPointer, outputBasesPointer := core.PrecomputeBasesCheck(points, precomputeFactor, outputBases)
cfg := GetDefaultMSMConfig()
cfg.PrecomputeFactor = precomputeFactor
pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases)
cPoints := (*C.affine_t)(pointsPointer)
cPointsLen := (C.int)(points.Len())
@@ -43,3 +48,16 @@ func PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c in
err := (cr.CudaError)(__ret)
return err
}
func PrecomputePoints(points core.HostOrDeviceSlice, msmSize int, cfg *core.MSMConfig, outputBases core.DeviceSlice) cr.CudaError {
pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases)
cPoints := (*C.affine_t)(pointsPointer)
cMsmSize := (C.int)(msmSize)
cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg))
cOutputBases := (*C.affine_t)(outputBasesPointer)
__ret := C.bls12_377_precompute_msm_points_cuda(cPoints, cMsmSize, cCfg, cOutputBases)
err := (cr.CudaError)(__ret)
return err
}

View File

@@ -210,9 +210,11 @@ func TestMSMG2Batch(t *testing.T) {
}
}
func TestPrecomputeBaseG2(t *testing.T) {
func TestPrecomputePointsG2(t *testing.T) {
cfg := g2.G2GetDefaultMSMConfig()
const precomputeFactor = 8
cfg.PrecomputeFactor = precomputeFactor
for _, power := range []int{10, 16} {
for _, batchSize := range []int{1, 3, 16} {
size := 1 << power
@@ -222,20 +224,18 @@ func TestPrecomputeBaseG2(t *testing.T) {
var precomputeOut core.DeviceSlice
_, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for PrecomputeBases results failed")
assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for PrecomputeBases results failed")
e = g2.G2PrecomputeBases(points, precomputeFactor, 0, &cfg.Ctx, precomputeOut)
assert.Equal(t, e, cr.CudaSuccess, "PrecomputeBases failed")
e = g2.G2PrecomputePoints(points, size, &cfg, precomputeOut)
assert.Equal(t, cr.CudaSuccess, e, "PrecomputeBases failed")
var p g2.G2Projective
var out core.DeviceSlice
_, e = out.Malloc(batchSize*p.Size(), p.Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed")
cfg.PrecomputeFactor = precomputeFactor
assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for Projective results failed")
e = g2.G2Msm(scalars, precomputeOut, &cfg, out)
assert.Equal(t, e, cr.CudaSuccess, "Msm failed")
assert.Equal(t, cr.CudaSuccess, e, "Msm failed")
outHost := make(core.HostSlice[g2.G2Projective], batchSize)
outHost.CopyFromDevice(&out)
out.Free()

View File

@@ -170,9 +170,11 @@ func TestMSMBatch(t *testing.T) {
}
}
func TestPrecomputeBase(t *testing.T) {
func TestPrecomputePoints(t *testing.T) {
cfg := msm.GetDefaultMSMConfig()
const precomputeFactor = 8
cfg.PrecomputeFactor = precomputeFactor
for _, power := range []int{10, 16} {
for _, batchSize := range []int{1, 3, 16} {
size := 1 << power
@@ -182,20 +184,18 @@ func TestPrecomputeBase(t *testing.T) {
var precomputeOut core.DeviceSlice
_, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for PrecomputeBases results failed")
assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for PrecomputeBases results failed")
e = msm.PrecomputeBases(points, precomputeFactor, 0, &cfg.Ctx, precomputeOut)
assert.Equal(t, e, cr.CudaSuccess, "PrecomputeBases failed")
e = msm.PrecomputePoints(points, size, &cfg, precomputeOut)
assert.Equal(t, cr.CudaSuccess, e, "PrecomputeBases failed")
var p icicleBls12_377.Projective
var out core.DeviceSlice
_, e = out.Malloc(batchSize*p.Size(), p.Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed")
cfg.PrecomputeFactor = precomputeFactor
assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for Projective results failed")
e = msm.Msm(scalars, precomputeOut, &cfg, out)
assert.Equal(t, e, cr.CudaSuccess, "Msm failed")
assert.Equal(t, cr.CudaSuccess, e, "Msm failed")
outHost := make(core.HostSlice[icicleBls12_377.Projective], batchSize)
outHost.CopyFromDevice(&out)
out.Free()

View File

@@ -16,6 +16,7 @@ typedef struct DeviceContext DeviceContext;
cudaError_t bls12_381_g2_msm_cuda(const scalar_t* scalars,const g2_affine_t* points, int count, MSMConfig* config, g2_projective_t* out);
cudaError_t bls12_381_g2_precompute_msm_bases_cuda(g2_affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, g2_affine_t* out);
cudaError_t bls12_381_g2_precompute_msm_points_cuda(g2_affine_t* points, int msm_size, MSMConfig* config, g2_affine_t* out);
#ifdef __cplusplus
}

View File

@@ -28,8 +28,13 @@ func G2Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *c
return err
}
// Deprecated: G2PrecomputeBases exists for backward compatibility.
// It may cause issues if an MSM with a different `c` value is used with precomputed points and it will be removed in a future version.
// G2PrecomputePoints should be used instead.
func G2PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError {
pointsPointer, outputBasesPointer := core.PrecomputeBasesCheck(points, precomputeFactor, outputBases)
cfg := G2GetDefaultMSMConfig()
cfg.PrecomputeFactor = precomputeFactor
pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases)
cPoints := (*C.g2_affine_t)(pointsPointer)
cPointsLen := (C.int)(points.Len())
@@ -43,3 +48,16 @@ func G2PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c
err := (cr.CudaError)(__ret)
return err
}
func G2PrecomputePoints(points core.HostOrDeviceSlice, msmSize int, cfg *core.MSMConfig, outputBases core.DeviceSlice) cr.CudaError {
pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases)
cPoints := (*C.g2_affine_t)(pointsPointer)
cMsmSize := (C.int)(msmSize)
cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg))
cOutputBases := (*C.g2_affine_t)(outputBasesPointer)
__ret := C.bls12_381_g2_precompute_msm_points_cuda(cPoints, cMsmSize, cCfg, cOutputBases)
err := (cr.CudaError)(__ret)
return err
}

View File

@@ -16,6 +16,7 @@ typedef struct DeviceContext DeviceContext;
cudaError_t bls12_381_msm_cuda(const scalar_t* scalars,const affine_t* points, int count, MSMConfig* config, projective_t* out);
cudaError_t bls12_381_precompute_msm_bases_cuda(affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, affine_t* out);
cudaError_t bls12_381_precompute_msm_points_cuda(affine_t* points, int msm_size, MSMConfig* config, affine_t* out);
#ifdef __cplusplus
}

View File

@@ -28,8 +28,13 @@ func Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *cor
return err
}
// Deprecated: PrecomputeBases exists for backward compatibility.
// It may cause issues if an MSM with a different `c` value is used with precomputed points and it will be removed in a future version.
// PrecomputePoints should be used instead.
func PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError {
pointsPointer, outputBasesPointer := core.PrecomputeBasesCheck(points, precomputeFactor, outputBases)
cfg := GetDefaultMSMConfig()
cfg.PrecomputeFactor = precomputeFactor
pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases)
cPoints := (*C.affine_t)(pointsPointer)
cPointsLen := (C.int)(points.Len())
@@ -43,3 +48,16 @@ func PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c in
err := (cr.CudaError)(__ret)
return err
}
func PrecomputePoints(points core.HostOrDeviceSlice, msmSize int, cfg *core.MSMConfig, outputBases core.DeviceSlice) cr.CudaError {
pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases)
cPoints := (*C.affine_t)(pointsPointer)
cMsmSize := (C.int)(msmSize)
cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg))
cOutputBases := (*C.affine_t)(outputBasesPointer)
__ret := C.bls12_381_precompute_msm_points_cuda(cPoints, cMsmSize, cCfg, cOutputBases)
err := (cr.CudaError)(__ret)
return err
}

View File

@@ -210,9 +210,11 @@ func TestMSMG2Batch(t *testing.T) {
}
}
func TestPrecomputeBaseG2(t *testing.T) {
func TestPrecomputePointsG2(t *testing.T) {
cfg := g2.G2GetDefaultMSMConfig()
const precomputeFactor = 8
cfg.PrecomputeFactor = precomputeFactor
for _, power := range []int{10, 16} {
for _, batchSize := range []int{1, 3, 16} {
size := 1 << power
@@ -222,20 +224,18 @@ func TestPrecomputeBaseG2(t *testing.T) {
var precomputeOut core.DeviceSlice
_, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for PrecomputeBases results failed")
assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for PrecomputeBases results failed")
e = g2.G2PrecomputeBases(points, precomputeFactor, 0, &cfg.Ctx, precomputeOut)
assert.Equal(t, e, cr.CudaSuccess, "PrecomputeBases failed")
e = g2.G2PrecomputePoints(points, size, &cfg, precomputeOut)
assert.Equal(t, cr.CudaSuccess, e, "PrecomputeBases failed")
var p g2.G2Projective
var out core.DeviceSlice
_, e = out.Malloc(batchSize*p.Size(), p.Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed")
cfg.PrecomputeFactor = precomputeFactor
assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for Projective results failed")
e = g2.G2Msm(scalars, precomputeOut, &cfg, out)
assert.Equal(t, e, cr.CudaSuccess, "Msm failed")
assert.Equal(t, cr.CudaSuccess, e, "Msm failed")
outHost := make(core.HostSlice[g2.G2Projective], batchSize)
outHost.CopyFromDevice(&out)
out.Free()

View File

@@ -170,9 +170,11 @@ func TestMSMBatch(t *testing.T) {
}
}
func TestPrecomputeBase(t *testing.T) {
func TestPrecomputePoints(t *testing.T) {
cfg := msm.GetDefaultMSMConfig()
const precomputeFactor = 8
cfg.PrecomputeFactor = precomputeFactor
for _, power := range []int{10, 16} {
for _, batchSize := range []int{1, 3, 16} {
size := 1 << power
@@ -182,20 +184,18 @@ func TestPrecomputeBase(t *testing.T) {
var precomputeOut core.DeviceSlice
_, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for PrecomputeBases results failed")
assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for PrecomputeBases results failed")
e = msm.PrecomputeBases(points, precomputeFactor, 0, &cfg.Ctx, precomputeOut)
assert.Equal(t, e, cr.CudaSuccess, "PrecomputeBases failed")
e = msm.PrecomputePoints(points, size, &cfg, precomputeOut)
assert.Equal(t, cr.CudaSuccess, e, "PrecomputeBases failed")
var p icicleBls12_381.Projective
var out core.DeviceSlice
_, e = out.Malloc(batchSize*p.Size(), p.Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed")
cfg.PrecomputeFactor = precomputeFactor
assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for Projective results failed")
e = msm.Msm(scalars, precomputeOut, &cfg, out)
assert.Equal(t, e, cr.CudaSuccess, "Msm failed")
assert.Equal(t, cr.CudaSuccess, e, "Msm failed")
outHost := make(core.HostSlice[icicleBls12_381.Projective], batchSize)
outHost.CopyFromDevice(&out)
out.Free()

View File

@@ -16,6 +16,7 @@ typedef struct DeviceContext DeviceContext;
cudaError_t bn254_g2_msm_cuda(const scalar_t* scalars,const g2_affine_t* points, int count, MSMConfig* config, g2_projective_t* out);
cudaError_t bn254_g2_precompute_msm_bases_cuda(g2_affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, g2_affine_t* out);
cudaError_t bn254_g2_precompute_msm_points_cuda(g2_affine_t* points, int msm_size, MSMConfig* config, g2_affine_t* out);
#ifdef __cplusplus
}

View File

@@ -28,8 +28,13 @@ func G2Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *c
return err
}
// Deprecated: G2PrecomputeBases exists for backward compatibility.
// It may cause issues if an MSM with a different `c` value is used with precomputed points and it will be removed in a future version.
// G2PrecomputePoints should be used instead.
func G2PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError {
pointsPointer, outputBasesPointer := core.PrecomputeBasesCheck(points, precomputeFactor, outputBases)
cfg := G2GetDefaultMSMConfig()
cfg.PrecomputeFactor = precomputeFactor
pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases)
cPoints := (*C.g2_affine_t)(pointsPointer)
cPointsLen := (C.int)(points.Len())
@@ -43,3 +48,16 @@ func G2PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c
err := (cr.CudaError)(__ret)
return err
}
func G2PrecomputePoints(points core.HostOrDeviceSlice, msmSize int, cfg *core.MSMConfig, outputBases core.DeviceSlice) cr.CudaError {
pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases)
cPoints := (*C.g2_affine_t)(pointsPointer)
cMsmSize := (C.int)(msmSize)
cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg))
cOutputBases := (*C.g2_affine_t)(outputBasesPointer)
__ret := C.bn254_g2_precompute_msm_points_cuda(cPoints, cMsmSize, cCfg, cOutputBases)
err := (cr.CudaError)(__ret)
return err
}

View File

@@ -16,6 +16,7 @@ typedef struct DeviceContext DeviceContext;
cudaError_t bn254_msm_cuda(const scalar_t* scalars,const affine_t* points, int count, MSMConfig* config, projective_t* out);
cudaError_t bn254_precompute_msm_bases_cuda(affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, affine_t* out);
cudaError_t bn254_precompute_msm_points_cuda(affine_t* points, int msm_size, MSMConfig* config, affine_t* out);
#ifdef __cplusplus
}

View File

@@ -28,8 +28,13 @@ func Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *cor
return err
}
// Deprecated: PrecomputeBases exists for backward compatibility.
// It may cause issues if an MSM with a different `c` value is used with precomputed points and it will be removed in a future version.
// PrecomputePoints should be used instead.
func PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError {
pointsPointer, outputBasesPointer := core.PrecomputeBasesCheck(points, precomputeFactor, outputBases)
cfg := GetDefaultMSMConfig()
cfg.PrecomputeFactor = precomputeFactor
pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases)
cPoints := (*C.affine_t)(pointsPointer)
cPointsLen := (C.int)(points.Len())
@@ -43,3 +48,16 @@ func PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c in
err := (cr.CudaError)(__ret)
return err
}
func PrecomputePoints(points core.HostOrDeviceSlice, msmSize int, cfg *core.MSMConfig, outputBases core.DeviceSlice) cr.CudaError {
pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases)
cPoints := (*C.affine_t)(pointsPointer)
cMsmSize := (C.int)(msmSize)
cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg))
cOutputBases := (*C.affine_t)(outputBasesPointer)
__ret := C.bn254_precompute_msm_points_cuda(cPoints, cMsmSize, cCfg, cOutputBases)
err := (cr.CudaError)(__ret)
return err
}

View File

@@ -210,9 +210,11 @@ func TestMSMG2Batch(t *testing.T) {
}
}
func TestPrecomputeBaseG2(t *testing.T) {
func TestPrecomputePointsG2(t *testing.T) {
cfg := g2.G2GetDefaultMSMConfig()
const precomputeFactor = 8
cfg.PrecomputeFactor = precomputeFactor
for _, power := range []int{10, 16} {
for _, batchSize := range []int{1, 3, 16} {
size := 1 << power
@@ -222,20 +224,18 @@ func TestPrecomputeBaseG2(t *testing.T) {
var precomputeOut core.DeviceSlice
_, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for PrecomputeBases results failed")
assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for PrecomputeBases results failed")
e = g2.G2PrecomputeBases(points, precomputeFactor, 0, &cfg.Ctx, precomputeOut)
assert.Equal(t, e, cr.CudaSuccess, "PrecomputeBases failed")
e = g2.G2PrecomputePoints(points, size, &cfg, precomputeOut)
assert.Equal(t, cr.CudaSuccess, e, "PrecomputeBases failed")
var p g2.G2Projective
var out core.DeviceSlice
_, e = out.Malloc(batchSize*p.Size(), p.Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed")
cfg.PrecomputeFactor = precomputeFactor
assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for Projective results failed")
e = g2.G2Msm(scalars, precomputeOut, &cfg, out)
assert.Equal(t, e, cr.CudaSuccess, "Msm failed")
assert.Equal(t, cr.CudaSuccess, e, "Msm failed")
outHost := make(core.HostSlice[g2.G2Projective], batchSize)
outHost.CopyFromDevice(&out)
out.Free()

View File

@@ -170,9 +170,11 @@ func TestMSMBatch(t *testing.T) {
}
}
func TestPrecomputeBase(t *testing.T) {
func TestPrecomputePoints(t *testing.T) {
cfg := msm.GetDefaultMSMConfig()
const precomputeFactor = 8
cfg.PrecomputeFactor = precomputeFactor
for _, power := range []int{10, 16} {
for _, batchSize := range []int{1, 3, 16} {
size := 1 << power
@@ -182,20 +184,18 @@ func TestPrecomputeBase(t *testing.T) {
var precomputeOut core.DeviceSlice
_, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for PrecomputeBases results failed")
assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for PrecomputeBases results failed")
e = msm.PrecomputeBases(points, precomputeFactor, 0, &cfg.Ctx, precomputeOut)
assert.Equal(t, e, cr.CudaSuccess, "PrecomputeBases failed")
e = msm.PrecomputePoints(points, size, &cfg, precomputeOut)
assert.Equal(t, cr.CudaSuccess, e, "PrecomputeBases failed")
var p icicleBn254.Projective
var out core.DeviceSlice
_, e = out.Malloc(batchSize*p.Size(), p.Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed")
cfg.PrecomputeFactor = precomputeFactor
assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for Projective results failed")
e = msm.Msm(scalars, precomputeOut, &cfg, out)
assert.Equal(t, e, cr.CudaSuccess, "Msm failed")
assert.Equal(t, cr.CudaSuccess, e, "Msm failed")
outHost := make(core.HostSlice[icicleBn254.Projective], batchSize)
outHost.CopyFromDevice(&out)
out.Free()

View File

@@ -16,6 +16,7 @@ typedef struct DeviceContext DeviceContext;
cudaError_t bw6_761_g2_msm_cuda(const scalar_t* scalars,const g2_affine_t* points, int count, MSMConfig* config, g2_projective_t* out);
cudaError_t bw6_761_g2_precompute_msm_bases_cuda(g2_affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, g2_affine_t* out);
cudaError_t bw6_761_g2_precompute_msm_points_cuda(g2_affine_t* points, int msm_size, MSMConfig* config, g2_affine_t* out);
#ifdef __cplusplus
}

View File

@@ -28,8 +28,13 @@ func G2Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *c
return err
}
// Deprecated: G2PrecomputeBases exists for backward compatibility.
// It may cause issues if an MSM with a different `c` value is used with precomputed points and it will be removed in a future version.
// G2PrecomputePoints should be used instead.
func G2PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError {
pointsPointer, outputBasesPointer := core.PrecomputeBasesCheck(points, precomputeFactor, outputBases)
cfg := G2GetDefaultMSMConfig()
cfg.PrecomputeFactor = precomputeFactor
pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases)
cPoints := (*C.g2_affine_t)(pointsPointer)
cPointsLen := (C.int)(points.Len())
@@ -43,3 +48,16 @@ func G2PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c
err := (cr.CudaError)(__ret)
return err
}
func G2PrecomputePoints(points core.HostOrDeviceSlice, msmSize int, cfg *core.MSMConfig, outputBases core.DeviceSlice) cr.CudaError {
pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases)
cPoints := (*C.g2_affine_t)(pointsPointer)
cMsmSize := (C.int)(msmSize)
cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg))
cOutputBases := (*C.g2_affine_t)(outputBasesPointer)
__ret := C.bw6_761_g2_precompute_msm_points_cuda(cPoints, cMsmSize, cCfg, cOutputBases)
err := (cr.CudaError)(__ret)
return err
}

View File

@@ -16,6 +16,7 @@ typedef struct DeviceContext DeviceContext;
cudaError_t bw6_761_msm_cuda(const scalar_t* scalars,const affine_t* points, int count, MSMConfig* config, projective_t* out);
cudaError_t bw6_761_precompute_msm_bases_cuda(affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, affine_t* out);
cudaError_t bw6_761_precompute_msm_points_cuda(affine_t* points, int msm_size, MSMConfig* config, affine_t* out);
#ifdef __cplusplus
}

View File

@@ -28,8 +28,13 @@ func Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *cor
return err
}
// Deprecated: PrecomputeBases exists for backward compatibility.
// It may cause issues if an MSM with a different `c` value is used with precomputed points and it will be removed in a future version.
// PrecomputePoints should be used instead.
func PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError {
pointsPointer, outputBasesPointer := core.PrecomputeBasesCheck(points, precomputeFactor, outputBases)
cfg := GetDefaultMSMConfig()
cfg.PrecomputeFactor = precomputeFactor
pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases)
cPoints := (*C.affine_t)(pointsPointer)
cPointsLen := (C.int)(points.Len())
@@ -43,3 +48,16 @@ func PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c in
err := (cr.CudaError)(__ret)
return err
}
func PrecomputePoints(points core.HostOrDeviceSlice, msmSize int, cfg *core.MSMConfig, outputBases core.DeviceSlice) cr.CudaError {
pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases)
cPoints := (*C.affine_t)(pointsPointer)
cMsmSize := (C.int)(msmSize)
cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg))
cOutputBases := (*C.affine_t)(outputBasesPointer)
__ret := C.bw6_761_precompute_msm_points_cuda(cPoints, cMsmSize, cCfg, cOutputBases)
err := (cr.CudaError)(__ret)
return err
}

View File

@@ -170,9 +170,11 @@ func TestMSMG2Batch(t *testing.T) {
}
}
func TestPrecomputeBaseG2(t *testing.T) {
func TestPrecomputePointsG2(t *testing.T) {
cfg := g2.G2GetDefaultMSMConfig()
const precomputeFactor = 8
cfg.PrecomputeFactor = precomputeFactor
for _, power := range []int{10, 16} {
for _, batchSize := range []int{1, 3, 16} {
size := 1 << power
@@ -182,20 +184,18 @@ func TestPrecomputeBaseG2(t *testing.T) {
var precomputeOut core.DeviceSlice
_, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for PrecomputeBases results failed")
assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for PrecomputeBases results failed")
e = g2.G2PrecomputeBases(points, precomputeFactor, 0, &cfg.Ctx, precomputeOut)
assert.Equal(t, e, cr.CudaSuccess, "PrecomputeBases failed")
e = g2.G2PrecomputePoints(points, size, &cfg, precomputeOut)
assert.Equal(t, cr.CudaSuccess, e, "PrecomputeBases failed")
var p g2.G2Projective
var out core.DeviceSlice
_, e = out.Malloc(batchSize*p.Size(), p.Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed")
cfg.PrecomputeFactor = precomputeFactor
assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for Projective results failed")
e = g2.G2Msm(scalars, precomputeOut, &cfg, out)
assert.Equal(t, e, cr.CudaSuccess, "Msm failed")
assert.Equal(t, cr.CudaSuccess, e, "Msm failed")
outHost := make(core.HostSlice[g2.G2Projective], batchSize)
outHost.CopyFromDevice(&out)
out.Free()

View File

@@ -170,9 +170,11 @@ func TestMSMBatch(t *testing.T) {
}
}
func TestPrecomputeBase(t *testing.T) {
func TestPrecomputePoints(t *testing.T) {
cfg := msm.GetDefaultMSMConfig()
const precomputeFactor = 8
cfg.PrecomputeFactor = precomputeFactor
for _, power := range []int{10, 16} {
for _, batchSize := range []int{1, 3, 16} {
size := 1 << power
@@ -182,20 +184,18 @@ func TestPrecomputeBase(t *testing.T) {
var precomputeOut core.DeviceSlice
_, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for PrecomputeBases results failed")
assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for PrecomputeBases results failed")
e = msm.PrecomputeBases(points, precomputeFactor, 0, &cfg.Ctx, precomputeOut)
assert.Equal(t, e, cr.CudaSuccess, "PrecomputeBases failed")
e = msm.PrecomputePoints(points, size, &cfg, precomputeOut)
assert.Equal(t, cr.CudaSuccess, e, "PrecomputeBases failed")
var p icicleBw6_761.Projective
var out core.DeviceSlice
_, e = out.Malloc(batchSize*p.Size(), p.Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed")
cfg.PrecomputeFactor = precomputeFactor
assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for Projective results failed")
e = msm.Msm(scalars, precomputeOut, &cfg, out)
assert.Equal(t, e, cr.CudaSuccess, "Msm failed")
assert.Equal(t, cr.CudaSuccess, e, "Msm failed")
outHost := make(core.HostSlice[icicleBw6_761.Projective], batchSize)
outHost.CopyFromDevice(&out)
out.Free()

View File

@@ -16,6 +16,7 @@ typedef struct DeviceContext DeviceContext;
cudaError_t grumpkin_msm_cuda(const scalar_t* scalars,const affine_t* points, int count, MSMConfig* config, projective_t* out);
cudaError_t grumpkin_precompute_msm_bases_cuda(affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, affine_t* out);
cudaError_t grumpkin_precompute_msm_points_cuda(affine_t* points, int msm_size, MSMConfig* config, affine_t* out);
#ifdef __cplusplus
}

View File

@@ -28,8 +28,13 @@ func Msm(scalars core.HostOrDeviceSlice, points core.HostOrDeviceSlice, cfg *cor
return err
}
// Deprecated: PrecomputeBases exists for backward compatibility.
// It may cause issues if an MSM with a different `c` value is used with precomputed points and it will be removed in a future version.
// PrecomputePoints should be used instead.
func PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError {
pointsPointer, outputBasesPointer := core.PrecomputeBasesCheck(points, precomputeFactor, outputBases)
cfg := GetDefaultMSMConfig()
cfg.PrecomputeFactor = precomputeFactor
pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases)
cPoints := (*C.affine_t)(pointsPointer)
cPointsLen := (C.int)(points.Len())
@@ -43,3 +48,16 @@ func PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c in
err := (cr.CudaError)(__ret)
return err
}
func PrecomputePoints(points core.HostOrDeviceSlice, msmSize int, cfg *core.MSMConfig, outputBases core.DeviceSlice) cr.CudaError {
pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases)
cPoints := (*C.affine_t)(pointsPointer)
cMsmSize := (C.int)(msmSize)
cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg))
cOutputBases := (*C.affine_t)(outputBasesPointer)
__ret := C.grumpkin_precompute_msm_points_cuda(cPoints, cMsmSize, cCfg, cOutputBases)
err := (cr.CudaError)(__ret)
return err
}

View File

@@ -64,9 +64,11 @@ func TestMSMBatch(t *testing.T) {
}
}
func TestPrecomputeBase(t *testing.T) {
func TestPrecomputePoints(t *testing.T) {
cfg := msm.GetDefaultMSMConfig()
const precomputeFactor = 8
cfg.PrecomputeFactor = precomputeFactor
for _, power := range []int{10, 16} {
for _, batchSize := range []int{1, 3, 16} {
size := 1 << power
@@ -76,20 +78,18 @@ func TestPrecomputeBase(t *testing.T) {
var precomputeOut core.DeviceSlice
_, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for PrecomputeBases results failed")
assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for PrecomputeBases results failed")
e = msm.PrecomputeBases(points, precomputeFactor, 0, &cfg.Ctx, precomputeOut)
assert.Equal(t, e, cr.CudaSuccess, "PrecomputeBases failed")
e = msm.PrecomputePoints(points, size, &cfg, precomputeOut)
assert.Equal(t, cr.CudaSuccess, e, "PrecomputeBases failed")
var p icicleGrumpkin.Projective
var out core.DeviceSlice
_, e = out.Malloc(batchSize*p.Size(), p.Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed")
cfg.PrecomputeFactor = precomputeFactor
assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for Projective results failed")
e = msm.Msm(scalars, precomputeOut, &cfg, out)
assert.Equal(t, e, cr.CudaSuccess, "Msm failed")
assert.Equal(t, cr.CudaSuccess, e, "Msm failed")
outHost := make(core.HostSlice[icicleGrumpkin.Projective], batchSize)
outHost.CopyFromDevice(&out)
out.Free()

View File

@@ -28,8 +28,13 @@ func {{.CurvePrefix}}Msm(scalars core.HostOrDeviceSlice, points core.HostOrDevic
return err
}
// Deprecated: {{.CurvePrefix}}PrecomputeBases exists for backward compatibility.
// It may cause issues if an MSM with a different `c` value is used with precomputed points and it will be removed in a future version.
// {{.CurvePrefix}}PrecomputePoints should be used instead.
func {{.CurvePrefix}}PrecomputeBases(points core.HostOrDeviceSlice, precomputeFactor int32, c int32, ctx *cr.DeviceContext, outputBases core.DeviceSlice) cr.CudaError {
pointsPointer, outputBasesPointer := core.PrecomputeBasesCheck(points, precomputeFactor, outputBases)
cfg := {{.CurvePrefix}}GetDefaultMSMConfig()
cfg.PrecomputeFactor = precomputeFactor
pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, &cfg, outputBases)
cPoints := (*C.{{toCName .CurvePrefix}}affine_t)(pointsPointer)
cPointsLen := (C.int)(points.Len())
@@ -43,3 +48,16 @@ func {{.CurvePrefix}}PrecomputeBases(points core.HostOrDeviceSlice, precomputeFa
err := (cr.CudaError)(__ret)
return err
}
func {{.CurvePrefix}}PrecomputePoints(points core.HostOrDeviceSlice, msmSize int, cfg *core.MSMConfig, outputBases core.DeviceSlice) cr.CudaError {
pointsPointer, outputBasesPointer := core.PrecomputePointsCheck(points, cfg, outputBases)
cPoints := (*C.{{toCName .CurvePrefix}}affine_t)(pointsPointer)
cMsmSize := (C.int)(msmSize)
cCfg := (*C.MSMConfig)(unsafe.Pointer(cfg))
cOutputBases := (*C.{{toCName .CurvePrefix}}affine_t)(outputBasesPointer)
__ret := C.{{.Curve}}{{toCNameBackwards .CurvePrefix}}_precompute_msm_points_cuda(cPoints, cMsmSize, cCfg, cOutputBases)
err := (cr.CudaError)(__ret)
return err
}

View File

@@ -16,6 +16,7 @@ typedef struct DeviceContext DeviceContext;
cudaError_t {{.Curve}}{{toCNameBackwards .CurvePrefix}}_msm_cuda(const scalar_t* scalars,const {{toCName .CurvePrefix}}affine_t* points, int count, MSMConfig* config, {{toCName .CurvePrefix}}projective_t* out);
cudaError_t {{.Curve}}{{toCNameBackwards .CurvePrefix}}_precompute_msm_bases_cuda({{toCName .CurvePrefix}}affine_t* points, int count, int precompute_factor, int _c, bool bases_on_device, DeviceContext* ctx, {{toCName .CurvePrefix}}affine_t* out);
cudaError_t {{.Curve}}{{toCNameBackwards .CurvePrefix}}_precompute_msm_points_cuda({{toCName .CurvePrefix}}affine_t* points, int msm_size, MSMConfig* config, {{toCName .CurvePrefix}}affine_t* out);
#ifdef __cplusplus
}

View File

@@ -251,9 +251,11 @@ func TestMSM{{.CurvePrefix}}Batch(t *testing.T) {
}
}
func TestPrecomputeBase{{.CurvePrefix}}(t *testing.T) {
func TestPrecomputePoints{{.CurvePrefix}}(t *testing.T) {
cfg := {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}GetDefaultMSMConfig()
const precomputeFactor = 8
cfg.PrecomputeFactor = precomputeFactor
for _, power := range []int{10, 16} {
for _, batchSize := range []int{1, 3, 16} {
size := 1 << power
@@ -263,20 +265,18 @@ func TestPrecomputeBase{{.CurvePrefix}}(t *testing.T) {
var precomputeOut core.DeviceSlice
_, e := precomputeOut.Malloc(points[0].Size()*points.Len()*int(precomputeFactor), points[0].Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for PrecomputeBases results failed")
assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for PrecomputeBases results failed")
e = {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}PrecomputeBases(points, precomputeFactor, 0, &cfg.Ctx, precomputeOut)
assert.Equal(t, e, cr.CudaSuccess, "PrecomputeBases failed")
e = {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}PrecomputePoints(points, size, &cfg, precomputeOut)
assert.Equal(t, cr.CudaSuccess, e, "PrecomputeBases failed")
var p {{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective
var out core.DeviceSlice
_, e = out.Malloc(batchSize*p.Size(), p.Size())
assert.Equal(t, e, cr.CudaSuccess, "Allocating bytes on device for Projective results failed")
cfg.PrecomputeFactor = precomputeFactor
assert.Equal(t, cr.CudaSuccess, e, "Allocating bytes on device for Projective results failed")
e = {{if eq .CurvePrefix "G2"}}g2{{else}}msm{{end}}.{{.CurvePrefix}}Msm(scalars, precomputeOut, &cfg, out)
assert.Equal(t, e, cr.CudaSuccess, "Msm failed")
assert.Equal(t, cr.CudaSuccess, e, "Msm failed")
outHost := make(core.HostSlice[{{if ne .CurvePrefix "G2"}}icicle{{capitalize .Curve}}{{else}}g2{{end}}.{{.CurvePrefix}}Projective], batchSize)
outHost.CopyFromDevice(&out)
out.Free()

View File

@@ -105,6 +105,13 @@ pub trait MSM<C: Curve> {
ctx: &DeviceContext,
output_bases: &mut DeviceSlice<Affine<C>>,
) -> IcicleResult<()>;
fn precompute_points_unchecked(
points: &(impl HostOrDeviceSlice<Affine<C>> + ?Sized),
msm_size: i32,
cfg: &MSMConfig,
output_bases: &mut DeviceSlice<Affine<C>>,
) -> IcicleResult<()>;
}
/// Computes the multi-scalar multiplication, or MSM: `s1*P1 + s2*P2 + ... + sn*Pn`, or a batch of several MSMs.
@@ -188,7 +195,7 @@ pub fn msm<C: Curve + MSM<C>>(
/// Extended points: \f$ P_0, P_1, P_2, ... P_{size}, 2^{l}P_0, 2^{l}P_1, ..., 2^{l}P_{size},
/// 2^{2l}P_0, 2^{2l}P_1, ..., 2^{2cl}P_{size}, ... \f$
///
/// * `bases` - Bases \f$ P_i \f$. In case of batch MSM, all *unique* points are concatenated.
/// * `points` - Bases \f$ P_i \f$. In case of batch MSM, all *unique* points are concatenated.
///
/// * `precompute_factor` - The number of total precomputed points for each base (including the base itself).
///
@@ -201,6 +208,7 @@ pub fn msm<C: Curve + MSM<C>>(
/// * `output_bases` - Device-allocated buffer of size `bases_size` * `precompute_factor` for the extended bases.
///
/// Returns `Ok(())` if no errors occurred or a `CudaError` otherwise.
#[deprecated(since = "2.5.0", note = "Please use `precompute_points` instead")]
pub fn precompute_bases<C: Curve + MSM<C>>(
points: &(impl HostOrDeviceSlice<Affine<C>> + ?Sized),
precompute_factor: i32,
@@ -220,6 +228,55 @@ pub fn precompute_bases<C: Curve + MSM<C>>(
C::precompute_bases_unchecked(points, precompute_factor, _c, ctx, output_bases)
}
/// A function that precomputes MSM bases by extending them with their shifted copies.
/// e.g.:
/// Original points: \f$ P_0, P_1, P_2, ... P_{size} \f$
/// Extended points: \f$ P_0, P_1, P_2, ... P_{size}, 2^{l}P_0, 2^{l}P_1, ..., 2^{l}P_{size},
/// 2^{2l}P_0, 2^{2l}P_1, ..., 2^{2cl}P_{size}, ... \f$
///
/// * `points` - Base points \f$ P_i \f$. In case of batch MSM, all *unique* points are concatenated.
///
/// * `msm_size` - The size of a single MSM to compute.
///
/// * `cfg` - config used to specify extra arguments of the MSM. NOTE: You should update the precompute_factor
/// and potentially the c value inside this config. This config should be the same config used in msm.
///
/// * `output_bases` - Device-allocated buffer of size `bases_size` * `precompute_factor` for the extended bases.
///
/// Returns `Ok(())` if no errors occurred or a `CudaError` otherwise.
pub fn precompute_points<C: Curve + MSM<C>>(
points: &(impl HostOrDeviceSlice<Affine<C>> + ?Sized),
msm_size: i32,
cfg: &MSMConfig,
output_bases: &mut DeviceSlice<Affine<C>>,
) -> IcicleResult<()> {
let precompute_factor = cfg.precompute_factor;
assert_eq!(
output_bases.len(),
points.len() * (precompute_factor as usize),
"Precompute factor is probably incorrect: expected {} but got {}",
output_bases.len() / points.len(),
precompute_factor
);
assert!(output_bases.is_on_device());
let ctx_device_id = cfg
.ctx
.device_id;
if let Some(device_id) = points.device_id() {
assert_eq!(
device_id, ctx_device_id,
"Device ids in points and context are different"
);
}
check_device(ctx_device_id);
let mut local_cfg = cfg.clone();
local_cfg.points_size = points.len() as i32;
local_cfg.are_points_on_device = points.is_on_device();
C::precompute_points_unchecked(points, msm_size, &local_cfg, output_bases)
}
#[macro_export]
macro_rules! impl_msm {
(
@@ -250,6 +307,14 @@ macro_rules! impl_msm {
ctx: &DeviceContext,
output_bases: *mut Affine<$curve>,
) -> CudaError;
#[link_name = concat!($curve_prefix, "_precompute_msm_points_cuda")]
pub(crate) fn precompute_points_cuda(
points: *const Affine<$curve>,
msm_size: i32,
cfg: &MSMConfig,
output_bases: *mut Affine<$curve>,
) -> CudaError;
}
}
@@ -292,6 +357,23 @@ macro_rules! impl_msm {
.wrap()
}
}
fn precompute_points_unchecked(
points: &(impl HostOrDeviceSlice<Affine<$curve>> + ?Sized),
msm_size: i32,
cfg: &MSMConfig,
output_bases: &mut DeviceSlice<Affine<$curve>>,
) -> IcicleResult<()> {
unsafe {
$curve_prefix_indent::precompute_points_cuda(
points.as_ptr(),
msm_size,
cfg,
output_bases.as_mut_ptr(),
)
.wrap()
}
}
}
};
}
@@ -363,7 +445,7 @@ macro_rules! impl_msm_bench {
group.sampling_mode(SamplingMode::Flat);
group.sample_size(10);
use icicle_core::msm::precompute_bases;
use icicle_core::msm::precompute_points;
use icicle_core::msm::tests::generate_random_affine_points_with_zeroes;
use icicle_cuda_runtime::stream::CudaStream;
@@ -396,11 +478,11 @@ macro_rules! impl_msm_bench {
let points = generate_random_affine_points_with_zeroes(test_size, 10);
for precompute_factor in [1, 4, 8] {
let mut precomputed_points_d = DeviceVec::cuda_malloc(precompute_factor * test_size).unwrap();
precompute_bases(
cfg.precompute_factor = precompute_factor as i32;
precompute_points(
HostSlice::from_slice(&points),
precompute_factor as i32,
0,
&cfg.ctx,
test_size as i32,
&cfg,
&mut precomputed_points_d,
)
.unwrap();
@@ -419,7 +501,6 @@ macro_rules! impl_msm_bench {
let scalars_h = HostSlice::from_slice(&scalars);
let mut msm_results = DeviceVec::<Projective<C>>::cuda_malloc(batch_size).unwrap();
cfg.precompute_factor = precompute_factor as i32;
let bench_descr = format!(
" {} x {} with precomp = {:?}",

View File

@@ -1,5 +1,5 @@
use crate::curve::{Affine, Curve, Projective};
use crate::msm::{msm, precompute_bases, MSMConfig, MSM};
use crate::msm::{msm, precompute_points, MSMConfig, MSM};
use crate::traits::{FieldImpl, GenerateRandom};
use icicle_cuda_runtime::device::{get_device_count, set_device, warmup};
use icicle_cuda_runtime::memory::{DeviceVec, HostSlice};
@@ -120,16 +120,16 @@ where
cfg.is_async = true;
cfg.large_bucket_factor = 5;
cfg.c = 4;
let precompute_factor = 8;
warmup(&stream).unwrap();
for test_size in test_sizes {
let precompute_factor = 8;
let points = generate_random_affine_points_with_zeroes(test_size, 10);
let mut precomputed_points_d = DeviceVec::cuda_malloc(precompute_factor * test_size).unwrap();
precompute_bases(
cfg.precompute_factor = precompute_factor as i32;
precompute_points(
HostSlice::from_slice(&points),
precompute_factor as i32,
0,
&cfg.ctx,
test_size as i32,
&cfg,
&mut precomputed_points_d,
)
.unwrap();